Skip to content

Commit

Permalink
Use implicit name resolution for TCP destinations
Browse files Browse the repository at this point in the history
When connecting to a TCP destination by name, go's implicit resolution
behavior tries all available addresses until it finds one that works
(fallback), with a preference for IPv6 if possible (happy eyeballs).
This is better than our current behavior (pick one IPv4 address).

The Outline client doesn't rely on named destinations, but other
Shadowsocks clients do.

This is an alternative to #100.

This change has one key difference from the previous behavior: IP
validation is enforced after the connection is established, not before.
A hostile user cannot use this to send data to a private service, but
they might be able to detect the existence of that service based on
how long the server waits before closing the connection.
  • Loading branch information
Ben Schwartz committed Jan 27, 2021
1 parent 4f3ce4d commit 8d6f171
Showing 1 changed file with 5 additions and 8 deletions.
13 changes: 5 additions & 8 deletions service/tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,15 @@ func (s *tcpService) SetTargetIPValidator(targetIPValidator onet.TargetIPValidat
}

func dialTarget(tgtAddr socks.Addr, proxyMetrics *metrics.ProxyMetrics, targetIPValidator onet.TargetIPValidator) (onet.DuplexConn, *onet.ConnectionError) {
tgtTCPAddr, err := net.ResolveTCPAddr("tcp", tgtAddr.String())
tgtConn, err := net.Dial("tcp", tgtAddr.String())
if err != nil {
return nil, onet.NewConnectionError("ERR_RESOLVE_ADDRESS", fmt.Sprintf("Failed to resolve target address %v", tgtAddr.String()), err)
return nil, onet.NewConnectionError("ERR_CONNECT", "Failed to connect to target", err)
}
if err := targetIPValidator(tgtTCPAddr.IP); err != nil {
tgtTCPConn := tgtConn.(*net.TCPConn)
if err := targetIPValidator(tgtTCPConn.RemoteAddr().(*net.TCPAddr).IP); err != nil {
tgtTCPConn.Close()
return nil, err
}

tgtTCPConn, err := net.DialTCP("tcp", nil, tgtTCPAddr)
if err != nil {
return nil, onet.NewConnectionError("ERR_CONNECT", "Failed to connect to target", err)
}
tgtTCPConn.SetKeepAlive(true)
return metrics.MeasureConn(tgtTCPConn, &proxyMetrics.ProxyTarget, &proxyMetrics.TargetProxy), nil
}
Expand Down

0 comments on commit 8d6f171

Please sign in to comment.