handleConnect is used to handle a connect command
(conn io.ReadWriter, req *Request)
| 50 | |
| 51 | // handleConnect is used to handle a connect command |
| 52 | func (h *StandardRequestHandler) handleConnect(conn io.ReadWriter, req *Request) error { |
| 53 | if h.accessPolicy != nil { |
| 54 | if req.DestAddr.IP == nil { |
| 55 | addr, err := net.ResolveIPAddr("ip", req.DestAddr.FQDN) |
| 56 | if err != nil { |
| 57 | _ = sendReply(conn, ruleFailure, req.DestAddr) |
| 58 | return fmt.Errorf("unable to resolve host to confirm access") |
| 59 | } |
| 60 | |
| 61 | req.DestAddr.IP = addr.IP |
| 62 | } |
| 63 | if allowed, rule := h.accessPolicy.Allowed(req.DestAddr.IP, req.DestAddr.Port); !allowed { |
| 64 | _ = sendReply(conn, ruleFailure, req.DestAddr) |
| 65 | if rule != nil { |
| 66 | return fmt.Errorf("Connect to %v denied due to iprule: %s", req.DestAddr, rule.String()) |
| 67 | } |
| 68 | return fmt.Errorf("Connect to %v denied", req.DestAddr) |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | target, localAddr, err := h.dialer.Dial(req.DestAddr.Address()) |
| 73 | if err != nil { |
| 74 | msg := err.Error() |
| 75 | resp := hostUnreachable |
| 76 | if strings.Contains(msg, "refused") { |
| 77 | resp = connectionRefused |
| 78 | } else if strings.Contains(msg, "network is unreachable") { |
| 79 | resp = networkUnreachable |
| 80 | } |
| 81 | if err := sendReply(conn, resp, nil); err != nil { |
| 82 | return fmt.Errorf("Failed to send reply: %v", err) |
| 83 | } |
| 84 | return fmt.Errorf("Connect to %v failed: %v", req.DestAddr, err) |
| 85 | } |
| 86 | defer target.Close() |
| 87 | |
| 88 | // Send success |
| 89 | if err := sendReply(conn, successReply, localAddr); err != nil { |
| 90 | return fmt.Errorf("Failed to send reply: %v", err) |
| 91 | } |
| 92 | |
| 93 | // Start proxying |
| 94 | proxyDone := make(chan error, 2) |
| 95 | |
| 96 | go func() { |
| 97 | _, e := io.Copy(target, req.bufConn) |
| 98 | proxyDone <- e |
| 99 | }() |
| 100 | |
| 101 | go func() { |
| 102 | _, e := io.Copy(conn, target) |
| 103 | proxyDone <- e |
| 104 | }() |
| 105 | |
| 106 | // Wait for both |
| 107 | for i := 0; i < 2; i++ { |
| 108 | e := <-proxyDone |
| 109 | if e != nil { |