(ctx Context, srv *Server, req *gossh.Request)
| 95 | } |
| 96 | |
| 97 | func (h *ForwardedTCPHandler) HandleSSHRequest(ctx Context, srv *Server, req *gossh.Request) (bool, []byte) { |
| 98 | h.Lock() |
| 99 | if h.forwards == nil { |
| 100 | h.forwards = make(map[string]net.Listener) |
| 101 | } |
| 102 | h.Unlock() |
| 103 | conn := ctx.Value(ContextKeyConn).(*gossh.ServerConn) |
| 104 | switch req.Type { |
| 105 | case "tcpip-forward": |
| 106 | var reqPayload remoteForwardRequest |
| 107 | if err := gossh.Unmarshal(req.Payload, &reqPayload); err != nil { |
| 108 | // TODO: log parse failure |
| 109 | return false, []byte{} |
| 110 | } |
| 111 | if srv.ReversePortForwardingCallback == nil || !srv.ReversePortForwardingCallback(ctx, reqPayload.BindAddr, reqPayload.BindPort) { |
| 112 | return false, []byte("port forwarding is disabled") |
| 113 | } |
| 114 | addr := net.JoinHostPort(reqPayload.BindAddr, strconv.Itoa(int(reqPayload.BindPort))) |
| 115 | ln, err := net.Listen("tcp", addr) |
| 116 | if err != nil { |
| 117 | // TODO: log listen failure |
| 118 | return false, []byte{} |
| 119 | } |
| 120 | _, destPortStr, _ := net.SplitHostPort(ln.Addr().String()) |
| 121 | destPort, _ := strconv.Atoi(destPortStr) |
| 122 | h.Lock() |
| 123 | h.forwards[addr] = ln |
| 124 | h.Unlock() |
| 125 | go func() { |
| 126 | <-ctx.Done() |
| 127 | h.Lock() |
| 128 | ln, ok := h.forwards[addr] |
| 129 | h.Unlock() |
| 130 | if ok { |
| 131 | ln.Close() |
| 132 | } |
| 133 | }() |
| 134 | go func() { |
| 135 | for { |
| 136 | c, err := ln.Accept() |
| 137 | if err != nil { |
| 138 | // TODO: log accept failure |
| 139 | break |
| 140 | } |
| 141 | originAddr, orignPortStr, _ := net.SplitHostPort(c.RemoteAddr().String()) |
| 142 | originPort, _ := strconv.Atoi(orignPortStr) |
| 143 | payload := gossh.Marshal(&remoteForwardChannelData{ |
| 144 | DestAddr: reqPayload.BindAddr, |
| 145 | DestPort: uint32(destPort), |
| 146 | OriginAddr: originAddr, |
| 147 | OriginPort: uint32(originPort), |
| 148 | }) |
| 149 | go func() { |
| 150 | ch, reqs, err := conn.OpenChannel(forwardedTCPChannelType, payload) |
| 151 | if err != nil { |
| 152 | // TODO: log failure to open channel |
| 153 | log.Println(err) |
| 154 | c.Close() |
nothing calls this directly
no test coverage detected