MCPcopy Create free account
hub / github.com/SenseUnit/dumbproxy / SOCKSHandler

Function SOCKSHandler

handler/socks.go:17–75  ·  view source on GitHub ↗
(dialer HandlerDialer, logger *clog.CondLogger, forward ForwardFunc)

Source from the content-addressed store, hash-verified

15)
16
17func SOCKSHandler(dialer HandlerDialer, logger *clog.CondLogger, forward ForwardFunc) func(ctx context.Context, writer io.Writer, request *socks5.Request) error {
18 var (
19 outboundMux sync.RWMutex
20 )
21 outbound := make(map[string]string)
22 isLoopback := func(addr string) (string, bool) {
23 outboundMux.RLock()
24 defer outboundMux.RUnlock()
25 originator, ok := outbound[addr]
26 return originator, ok
27 }
28 return func(ctx context.Context, writer io.Writer, request *socks5.Request) error {
29 if originator, isLoopback := isLoopback(request.RemoteAddr.String()); isLoopback {
30 logger.Critical("Loopback tunnel detected: %s is an outbound "+
31 "address for another request from %s", request.RemoteAddr.String(), originator)
32 socks5.SendReply(writer, statute.RepConnectionRefused, nil)
33 return fmt.Errorf("Loopback tunnel detected: %s is an outbound "+
34 "address for another request from %s", request.RemoteAddr.String(), originator)
35 }
36 username := ""
37 if request.AuthContext != nil {
38 username = request.AuthContext.Payload["username"]
39 }
40 localAddr := request.LocalAddr.String()
41 ctx = ddto.BoundDialerParamsToContext(ctx, nil, trimAddrPort(localAddr))
42 ctx = ddto.FilterParamsToContext(ctx, nil, username)
43 logger.Info("Request: %v => %v %q %v %v %v", request.RemoteAddr, localAddr, username, "SOCKS5", "CONNECT", request.DestAddr)
44 target, err := dialer.DialContext(ctx, "tcp", request.DestAddr.String())
45 if err != nil {
46 msg := err.Error()
47 resp := statute.RepHostUnreachable
48 if strings.Contains(msg, "refused") {
49 resp = statute.RepConnectionRefused
50 } else if strings.Contains(msg, "network is unreachable") {
51 resp = statute.RepNetworkUnreachable
52 }
53 if err := socks5.SendReply(writer, resp, nil); err != nil {
54 return fmt.Errorf("failed to send reply: %w", err)
55 }
56 return fmt.Errorf("connect to %v failed: %w", request.RawDestAddr, err)
57 }
58 outboundMux.Lock()
59 outbound[target.LocalAddr().String()] = request.RemoteAddr.String()
60 outboundMux.Unlock()
61 defer func() {
62 target.Close() // nolint: errcheck
63 outboundMux.Lock()
64 delete(outbound, localAddr)
65 outboundMux.Unlock()
66 }()
67
68 // Send success
69 if err := socks5.SendReply(writer, statute.RepSuccess, target.LocalAddr()); err != nil {
70 return fmt.Errorf("failed to send reply, %v", err)
71 }
72
73 return forward(ctx, username, wrapSOCKS(request.Reader, writer), target, "tcp", request.DestAddr.String())
74 }

Callers 1

runFunction · 0.92

Calls 10

trimAddrPortFunction · 0.85
wrapSOCKSFunction · 0.85
CriticalMethod · 0.80
ErrorfMethod · 0.80
DialContextMethod · 0.65
CloseMethod · 0.65
StringMethod · 0.45
InfoMethod · 0.45
ErrorMethod · 0.45
LocalAddrMethod · 0.45

Tested by

no test coverage detected