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