| Serge Bazanski | be74284 | 2022-04-04 13:18:50 +0200 | [diff] [blame] | 1 | package main |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "fmt" |
| 6 | "net" |
| 7 | |
| Tim Windelschmidt | 9f21f53 | 2024-05-07 15:14:20 +0200 | [diff] [blame^] | 8 | "source.monogon.dev/osbase/socksproxy" |
| 9 | "source.monogon.dev/osbase/supervisor" |
| Serge Bazanski | be74284 | 2022-04-04 13:18:50 +0200 | [diff] [blame] | 10 | ) |
| 11 | |
| Tim Windelschmidt | a3cd52c | 2024-04-18 23:21:16 +0200 | [diff] [blame] | 12 | // SOCKSPort is the port at which nanoswitch listens for SOCKS conenctions. |
| 13 | // |
| Tim Windelschmidt | 9f21f53 | 2024-05-07 15:14:20 +0200 | [diff] [blame^] | 14 | // ONCHANGE(//metropolis/test/launch:cluster.go): port must be kept in sync |
| Serge Bazanski | be74284 | 2022-04-04 13:18:50 +0200 | [diff] [blame] | 15 | const SOCKSPort uint16 = 1080 |
| 16 | |
| 17 | // socksHandler implements a socksproxy.Handler which permits and logs |
| 18 | // connections to the nanoswitch network. |
| 19 | type socksHandler struct{} |
| 20 | |
| 21 | func (s *socksHandler) Connect(ctx context.Context, req *socksproxy.ConnectRequest) *socksproxy.ConnectResponse { |
| 22 | logger := supervisor.Logger(ctx) |
| 23 | target := net.JoinHostPort(req.Address.String(), fmt.Sprintf("%d", req.Port)) |
| 24 | |
| 25 | if len(req.Address) != 4 { |
| 26 | logger.Warningf("Connect %s: wrong address type", target) |
| 27 | return &socksproxy.ConnectResponse{ |
| 28 | Error: socksproxy.ReplyAddressTypeNotSupported, |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | addr := req.Address |
| 33 | switchCIDR := net.IPNet{ |
| 34 | IP: switchIP.Mask(switchSubnetMask), |
| 35 | Mask: switchSubnetMask, |
| 36 | } |
| 37 | if !switchCIDR.Contains(addr) || switchCIDR.IP.Equal(addr) { |
| 38 | logger.Warningf("Connect %s: not in switch network", target) |
| 39 | return &socksproxy.ConnectResponse{ |
| 40 | Error: socksproxy.ReplyNetworkUnreachable, |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | con, err := net.Dial("tcp", target) |
| 45 | if err != nil { |
| 46 | logger.Warningf("Connect %s: dial failed: %v", target, err) |
| 47 | return &socksproxy.ConnectResponse{ |
| 48 | Error: socksproxy.ReplyHostUnreachable, |
| 49 | } |
| 50 | } |
| 51 | res, err := socksproxy.ConnectResponseFromConn(con) |
| 52 | if err != nil { |
| 53 | logger.Warningf("Connect %s: could not make SOCKS response: %v", target, err) |
| Serge Bazanski | 1ec1fe9 | 2023-03-22 18:29:28 +0100 | [diff] [blame] | 54 | con.Close() |
| Serge Bazanski | be74284 | 2022-04-04 13:18:50 +0200 | [diff] [blame] | 55 | return &socksproxy.ConnectResponse{ |
| 56 | Error: socksproxy.ReplyGeneralFailure, |
| 57 | } |
| 58 | } |
| 59 | logger.Infof("Connect %s: established", target) |
| 60 | return res |
| 61 | } |
| 62 | |
| 63 | // runSOCKSProxy starts a SOCKS proxy to the nanoswitchnetwork at SOCKSPort. |
| 64 | func runSOCKSProxy(ctx context.Context) error { |
| 65 | lis, err := net.Listen("tcp", fmt.Sprintf(":%d", SOCKSPort)) |
| 66 | if err != nil { |
| Tim Windelschmidt | adcf5d7 | 2024-05-21 13:46:25 +0200 | [diff] [blame] | 67 | return fmt.Errorf("failed to listen on :%d : %w", SOCKSPort, err) |
| Serge Bazanski | be74284 | 2022-04-04 13:18:50 +0200 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | h := &socksHandler{} |
| 71 | supervisor.Signal(ctx, supervisor.SignalHealthy) |
| 72 | return socksproxy.Serve(ctx, h, lis) |
| 73 | } |