Skip to content

Commit a11a3dd

Browse files
committed
server: add reverse port forwarding restrictions
Although reverse port forwarding (sharing client ports with the server) should not generally leak any resources from the server to the client, the facility may nevertheless be abused if the client is able to open a server port which is otherwise meant for some other purpose on the server. (This might happen, for instance, if a service on the server has crashed or becomes somehow disabled, thus freeing the port which would otherwise be occupied by the service.) To mitigate such potential abuse, disable reverse port forwarding by default and introduce server option --reverse to enable it explicitly. Additionally, subject reverse port forwarding remotes to server-side --authfile restrictions (for instance, "^R:0.0.0.0:7000$").
1 parent 8724c90 commit a11a3dd

File tree

5 files changed

+31
-7
lines changed

5 files changed

+31
-7
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ $ chisel server --help
104104
when <user> connects, their <pass> will be verified and then
105105
each of the remote addresses will be compared against the list
106106
of address regular expressions for a match. Addresses will
107-
always come in the form "<host/ip>:<port>".
107+
always come in the form "<remote-host>:<remote-port>" for normal remotes
108+
and "R:<local-interface>:<local-port>" for reverse port forwarding
109+
remotes. This file will be automatically reloaded on change.
108110
109111
--auth, An optional string representing a single user with full
110112
access, in the form of <user:pass>. This is equivalent to creating an
@@ -117,6 +119,9 @@ $ chisel server --help
117119
--socks5, Allows client to access the internal SOCKS5 proxy. See
118120
chisel client --help for more information.
119121
122+
--reverse, Allows client to specify reverse port forwarding remotes
123+
in addition to normal remotes.
124+
120125
--pid Generate pid file in current directory
121126
122127
-v, Enable verbose logging

example/users.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
],
88
"ping:pong": [
99
"^0.0.0.0:[45]000$",
10-
"^example.com:80$"
10+
"^example.com:80$",
11+
"^R:0.0.0.0:7000$"
1112
]
12-
}
13+
}

main.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,9 @@ var serverHelp = `
107107
when <user> connects, their <pass> will be verified and then
108108
each of the remote addresses will be compared against the list
109109
of address regular expressions for a match. Addresses will
110-
always come in the form "<host/ip>:<port>". This file will be
111-
automatically reloaded on change.
110+
always come in the form "<remote-host>:<remote-port>" for normal remotes
111+
and "R:<local-interface>:<local-port>" for reverse port forwarding
112+
remotes. This file will be automatically reloaded on change.
112113
113114
--auth, An optional string representing a single user with full
114115
access, in the form of <user:pass>. This is equivalent to creating an
@@ -120,6 +121,9 @@ var serverHelp = `
120121
121122
--socks5, Allows client to access the internal SOCKS5 proxy. See
122123
chisel client --help for more information.
124+
125+
--reverse, Allows client to specify reverse port forwarding remotes
126+
in addition to normal remotes.
123127
` + commonHelp
124128

125129
func server(args []string) {
@@ -134,6 +138,7 @@ func server(args []string) {
134138
auth := flags.String("auth", "", "")
135139
proxy := flags.String("proxy", "", "")
136140
socks5 := flags.Bool("socks5", false, "")
141+
reverse := flags.Bool("reverse", false, "")
137142
pid := flags.Bool("pid", false, "")
138143
verbose := flags.Bool("v", false, "")
139144

@@ -167,6 +172,7 @@ func server(args []string) {
167172
Auth: *auth,
168173
Proxy: *proxy,
169174
Socks5: *socks5,
175+
Reverse: *reverse,
170176
})
171177
if err != nil {
172178
log.Fatal(err)

server/handler.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,23 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, req *http.Request) {
9595
clog.Infof("Client version (%s) differs from server version (%s)",
9696
v, chshare.BuildVersion)
9797
}
98+
for _, r := range c.Remotes {
99+
if r.Reverse && !s.reverseOk {
100+
clog.Debugf("Denied reverse port forwarding request, please enable --reverse")
101+
failed(s.Errorf("Reverse port forwaring not enabled on server"))
102+
return
103+
}
104+
}
98105
//if user is provided, ensure they have
99106
//access to the desired remotes
100107
if user != nil {
101108
for _, r := range c.Remotes {
109+
var addr string
102110
if r.Reverse {
103-
continue
111+
addr = "R:" + r.LocalHost + ":" + r.LocalPort
112+
} else {
113+
addr = r.RemoteHost + ":" + r.RemotePort
104114
}
105-
addr := r.RemoteHost + ":" + r.RemotePort
106115
if !user.HasAccess(addr) {
107116
failed(s.Errorf("access to '%s' denied", addr))
108117
return

server/server.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type Config struct {
2525
Auth string
2626
Proxy string
2727
Socks5 bool
28+
Reverse bool
2829
}
2930

3031
// Server respresent a chisel service
@@ -39,6 +40,7 @@ type Server struct {
3940
socksServer *socks5.Server
4041
sshConfig *ssh.ServerConfig
4142
users *chshare.UserIndex
43+
reverseOk bool
4244
}
4345

4446
var upgrader = websocket.Upgrader{
@@ -53,6 +55,7 @@ func NewServer(config *Config) (*Server, error) {
5355
httpServer: chshare.NewHTTPServer(),
5456
Logger: chshare.NewLogger("server"),
5557
sessions: chshare.Users{},
58+
reverseOk: config.Reverse,
5659
}
5760
s.Info = true
5861
s.users = chshare.NewUserIndex(s.Logger)

0 commit comments

Comments
 (0)