55 "errors"
66 "io"
77 "net"
8+ "net/netip"
89 "os"
910 "sync"
1011 "time"
@@ -117,28 +118,38 @@ func (s *TCPRelay) Start(ctx context.Context) error {
117118}
118119
119120// handleConn handles an accepted TCP connection.
120- func (s * TCPRelay ) handleConn (ctx context.Context , lnc * tcpRelayListener , clientTCPConn * net. TCPConn ) {
121- var clientConn netio.Conn
121+ func (s * TCPRelay ) handleConn (ctx context.Context , lnc * tcpRelayListener , acceptedConn netio. Conn ) {
122+ var inConn netio.Conn
122123 defer func () {
123- if clientConn != nil {
124- _ = clientConn .Close ()
124+ if inConn != nil {
125+ _ = inConn .Close ()
125126 } else {
126- _ = clientTCPConn .Close ()
127+ _ = acceptedConn .Close ()
127128 }
128129 }()
129130
130- // Get client address.
131- clientAddrPort := clientTCPConn .RemoteAddr ().(* net.TCPAddr ).AddrPort ()
132- clientAddress := clientAddrPort .String ()
131+ var (
132+ clientAddrPort netip.AddrPort
133+ clientAddress string
134+ )
135+ clientAddr := acceptedConn .RemoteAddr ()
136+ if clientTCPAddr , ok := clientAddr .(* net.TCPAddr ); ok {
137+ clientAddrPort = clientTCPAddr .AddrPort ()
138+ // Unlike net.TCPAddr.String, netip.AddrPort.String preserves IPv4-mapped IPv6 addresses.
139+ clientAddress = clientAddrPort .String ()
140+ } else {
141+ clientAddress = clientAddr .String ()
142+ }
143+
133144 logger := lnc .logger .With (
134145 zap .String ("clientAddress" , clientAddress ),
135146 )
136147
137148 // Handshake.
138- req , err := s .server .HandleStream (clientTCPConn , logger )
149+ req , err := s .server .HandleStream (acceptedConn , logger )
139150 if err != nil {
140151 if err == netio .ErrHandleStreamDone {
141- logger .Debug ("Handled TCP connection without bidirectional copy" )
152+ logger .Debug ("Handled stream connection without bidirectional copy" )
142153 return
143154 }
144155 logger .Warn ("Failed to complete handshake with client" , zap .Error (err ))
@@ -189,20 +200,20 @@ func (s *TCPRelay) handleConn(ctx context.Context, lnc *tcpRelayListener, client
189200 // 3. server did not return initial payload
190201 // 4. client has native support
191202 if len (req .Payload ) == 0 && clientInfo .NativeInitialPayload && lnc .waitForInitialPayload {
192- clientConn , err = req .PendingConn .Proceed ()
203+ inConn , err = req .PendingConn .Proceed ()
193204 if err != nil {
194205 logger .Warn ("Failed to proceed with pending connection" , zap .Error (err ))
195206 return
196207 }
197208
198209 req .Payload = make ([]byte , lnc .initialPayloadWaitBufferSize )
199210
200- if err = clientConn .SetReadDeadline (time .Now ().Add (lnc .initialPayloadWaitTimeout )); err != nil {
211+ if err = inConn .SetReadDeadline (time .Now ().Add (lnc .initialPayloadWaitTimeout )); err != nil {
201212 logger .Error ("Failed to set read deadline to initial payload wait timeout" , zap .Error (err ))
202213 return
203214 }
204215
205- payloadLength , err := clientConn .Read (req .Payload )
216+ payloadLength , err := inConn .Read (req .Payload )
206217 switch {
207218 case err == nil :
208219 if ce := logger .Check (zap .DebugLevel , "Got initial payload" ); ce != nil {
@@ -230,31 +241,31 @@ func (s *TCPRelay) handleConn(ctx context.Context, lnc *tcpRelayListener, client
230241
231242 req .Payload = req .Payload [:payloadLength ]
232243
233- if err = clientConn .SetReadDeadline (time.Time {}); err != nil {
244+ if err = inConn .SetReadDeadline (time.Time {}); err != nil {
234245 logger .Error ("Failed to reset read deadline" , zap .Error (err ))
235246 return
236247 }
237248 }
238249
239- // Create remote connection.
240- remoteConn , err := dialer .DialStream (ctx , req .Addr , req .Payload )
250+ // Open outgoing connection to destination address .
251+ outConn , err := dialer .DialStream (ctx , req .Addr , req .Payload )
241252 if err != nil {
242- logger .Warn ("Failed to create remote connection" ,
253+ logger .Warn ("Failed to open outgoing connection" ,
243254 zap .Int ("initialPayloadLength" , len (req .Payload )),
244255 zap .Error (err ),
245256 )
246- if clientConn == nil {
257+ if inConn == nil {
247258 dialResult := conn .DialResultFromError (err )
248259 if err = req .Abort (dialResult ); err != nil {
249260 logger .Warn ("Failed to abort pending connection" , zap .Error (err ))
250261 }
251262 }
252263 return
253264 }
254- defer remoteConn .Close ()
265+ defer outConn .Close ()
255266
256- if clientConn == nil {
257- clientConn , err = req .PendingConn .Proceed ()
267+ if inConn == nil {
268+ inConn , err = req .PendingConn .Proceed ()
258269 if err != nil {
259270 logger .Warn ("Failed to proceed with pending connection" , zap .Error (err ))
260271 return
@@ -266,7 +277,7 @@ func (s *TCPRelay) handleConn(ctx context.Context, lnc *tcpRelayListener, client
266277 )
267278
268279 // Bidirectional copy.
269- nl2r , nr2l , err := netio .BidirectionalCopy (clientConn , remoteConn )
280+ nl2r , nr2l , err := netio .BidirectionalCopy (inConn , outConn )
270281 nl2r += int64 (len (req .Payload ))
271282 s .collector .CollectTCPSession (req .Username , uint64 (nr2l ), uint64 (nl2r ))
272283 if err != nil {
0 commit comments