blob: 7b0278a44579198e4d8ea109c2f8effa01223d30 [file] [log] [blame]
package main
import (
"context"
"fmt"
"net"
"source.monogon.dev/metropolis/pkg/socksproxy"
"source.monogon.dev/metropolis/pkg/supervisor"
)
// ONCHANGE(//metropolis/test/launch/cluster:cluster.go): port must be kept in sync
const SOCKSPort uint16 = 1080
// socksHandler implements a socksproxy.Handler which permits and logs
// connections to the nanoswitch network.
type socksHandler struct{}
func (s *socksHandler) Connect(ctx context.Context, req *socksproxy.ConnectRequest) *socksproxy.ConnectResponse {
logger := supervisor.Logger(ctx)
target := net.JoinHostPort(req.Address.String(), fmt.Sprintf("%d", req.Port))
if len(req.Address) != 4 {
logger.Warningf("Connect %s: wrong address type", target)
return &socksproxy.ConnectResponse{
Error: socksproxy.ReplyAddressTypeNotSupported,
}
}
addr := req.Address
switchCIDR := net.IPNet{
IP: switchIP.Mask(switchSubnetMask),
Mask: switchSubnetMask,
}
if !switchCIDR.Contains(addr) || switchCIDR.IP.Equal(addr) {
logger.Warningf("Connect %s: not in switch network", target)
return &socksproxy.ConnectResponse{
Error: socksproxy.ReplyNetworkUnreachable,
}
}
con, err := net.Dial("tcp", target)
if err != nil {
logger.Warningf("Connect %s: dial failed: %v", target, err)
return &socksproxy.ConnectResponse{
Error: socksproxy.ReplyHostUnreachable,
}
}
res, err := socksproxy.ConnectResponseFromConn(con)
if err != nil {
logger.Warningf("Connect %s: could not make SOCKS response: %v", target, err)
return &socksproxy.ConnectResponse{
Error: socksproxy.ReplyGeneralFailure,
}
}
logger.Infof("Connect %s: established", target)
return res
}
// runSOCKSProxy starts a SOCKS proxy to the nanoswitchnetwork at SOCKSPort.
func runSOCKSProxy(ctx context.Context) error {
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", SOCKSPort))
if err != nil {
return fmt.Errorf("failed to listen on :%d : %v", SOCKSPort, err)
}
h := &socksHandler{}
supervisor.Signal(ctx, supervisor.SignalHealthy)
return socksproxy.Serve(ctx, h, lis)
}