blob: 4ba1d0af23639496d1c62ca1444bdc2f7796e631 [file] [log] [blame]
Tim Windelschmidt6d33a432025-02-04 14:34:25 +01001// Copyright The Monogon Project Authors.
2// SPDX-License-Identifier: Apache-2.0
3
Serge Bazanskibe742842022-04-04 13:18:50 +02004package main
5
6import (
7 "context"
8 "fmt"
9 "net"
10
Tim Windelschmidt9f21f532024-05-07 15:14:20 +020011 "source.monogon.dev/osbase/socksproxy"
12 "source.monogon.dev/osbase/supervisor"
Serge Bazanskibe742842022-04-04 13:18:50 +020013)
14
Tim Windelschmidta3cd52c2024-04-18 23:21:16 +020015// SOCKSPort is the port at which nanoswitch listens for SOCKS conenctions.
16//
Tim Windelschmidt9f21f532024-05-07 15:14:20 +020017// ONCHANGE(//metropolis/test/launch:cluster.go): port must be kept in sync
Serge Bazanskibe742842022-04-04 13:18:50 +020018const SOCKSPort uint16 = 1080
19
20// socksHandler implements a socksproxy.Handler which permits and logs
21// connections to the nanoswitch network.
22type socksHandler struct{}
23
24func (s *socksHandler) Connect(ctx context.Context, req *socksproxy.ConnectRequest) *socksproxy.ConnectResponse {
25 logger := supervisor.Logger(ctx)
26 target := net.JoinHostPort(req.Address.String(), fmt.Sprintf("%d", req.Port))
27
28 if len(req.Address) != 4 {
29 logger.Warningf("Connect %s: wrong address type", target)
30 return &socksproxy.ConnectResponse{
31 Error: socksproxy.ReplyAddressTypeNotSupported,
32 }
33 }
34
35 addr := req.Address
36 switchCIDR := net.IPNet{
37 IP: switchIP.Mask(switchSubnetMask),
38 Mask: switchSubnetMask,
39 }
40 if !switchCIDR.Contains(addr) || switchCIDR.IP.Equal(addr) {
41 logger.Warningf("Connect %s: not in switch network", target)
42 return &socksproxy.ConnectResponse{
43 Error: socksproxy.ReplyNetworkUnreachable,
44 }
45 }
46
47 con, err := net.Dial("tcp", target)
48 if err != nil {
49 logger.Warningf("Connect %s: dial failed: %v", target, err)
50 return &socksproxy.ConnectResponse{
51 Error: socksproxy.ReplyHostUnreachable,
52 }
53 }
54 res, err := socksproxy.ConnectResponseFromConn(con)
55 if err != nil {
56 logger.Warningf("Connect %s: could not make SOCKS response: %v", target, err)
Serge Bazanski1ec1fe92023-03-22 18:29:28 +010057 con.Close()
Serge Bazanskibe742842022-04-04 13:18:50 +020058 return &socksproxy.ConnectResponse{
59 Error: socksproxy.ReplyGeneralFailure,
60 }
61 }
62 logger.Infof("Connect %s: established", target)
63 return res
64}
65
66// runSOCKSProxy starts a SOCKS proxy to the nanoswitchnetwork at SOCKSPort.
67func runSOCKSProxy(ctx context.Context) error {
68 lis, err := net.Listen("tcp", fmt.Sprintf(":%d", SOCKSPort))
69 if err != nil {
Tim Windelschmidtadcf5d72024-05-21 13:46:25 +020070 return fmt.Errorf("failed to listen on :%d : %w", SOCKSPort, err)
Serge Bazanskibe742842022-04-04 13:18:50 +020071 }
72
73 h := &socksHandler{}
74 supervisor.Signal(ctx, supervisor.SignalHealthy)
75 return socksproxy.Serve(ctx, h, lis)
76}