github.com/database64128/shadowsocks-go@v1.7.0/service/client.go (about) 1 package service 2 3 import ( 4 "fmt" 5 "net/netip" 6 7 "github.com/database64128/shadowsocks-go/conn" 8 "github.com/database64128/shadowsocks-go/direct" 9 "github.com/database64128/shadowsocks-go/http" 10 "github.com/database64128/shadowsocks-go/ss2022" 11 "github.com/database64128/shadowsocks-go/zerocopy" 12 "go.uber.org/zap" 13 ) 14 15 // ClientConfig stores a client configuration. 16 // It may be marshaled as or unmarshaled from JSON. 17 type ClientConfig struct { 18 Name string `json:"name"` 19 Endpoint conn.Addr `json:"endpoint"` 20 Protocol string `json:"protocol"` 21 DialerFwmark int `json:"dialerFwmark"` 22 DialerTrafficClass int `json:"dialerTrafficClass"` 23 24 // TCP 25 EnableTCP bool `json:"enableTCP"` 26 DialerTFO bool `json:"dialerTFO"` 27 28 // UDP 29 EnableUDP bool `json:"enableUDP"` 30 MTU int `json:"mtu"` 31 32 // Shadowsocks 33 PSK []byte `json:"psk"` 34 IPSKs [][]byte `json:"iPSKs"` 35 PaddingPolicy string `json:"paddingPolicy"` 36 cipherConfig *ss2022.ClientCipherConfig 37 38 // Taint 39 UnsafeRequestStreamPrefix []byte `json:"unsafeRequestStreamPrefix"` 40 UnsafeResponseStreamPrefix []byte `json:"unsafeResponseStreamPrefix"` 41 42 listenConfigCache conn.ListenConfigCache 43 dialerCache conn.DialerCache 44 logger *zap.Logger 45 } 46 47 // Initialize initializes the client configuration. 48 func (cc *ClientConfig) Initialize(listenConfigCache conn.ListenConfigCache, dialerCache conn.DialerCache, logger *zap.Logger) error { 49 switch cc.Protocol { 50 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 51 err := ss2022.CheckPSKLength(cc.Protocol, cc.PSK, cc.IPSKs) 52 if err != nil { 53 return err 54 } 55 cc.cipherConfig, err = ss2022.NewClientCipherConfig(cc.PSK, cc.IPSKs, cc.EnableUDP) 56 if err != nil { 57 return err 58 } 59 } 60 cc.listenConfigCache = listenConfigCache 61 cc.dialerCache = dialerCache 62 cc.logger = logger 63 return nil 64 } 65 66 // TCPClient creates a zerocopy.TCPClient from the ClientConfig. 67 func (cc *ClientConfig) TCPClient() (zerocopy.TCPClient, error) { 68 if !cc.EnableTCP { 69 return nil, errNetworkDisabled 70 } 71 72 dialer := cc.dialerCache.Get(conn.DialerSocketOptions{ 73 Fwmark: cc.DialerFwmark, 74 TrafficClass: cc.DialerTrafficClass, 75 TCPFastOpen: cc.DialerTFO, 76 }) 77 78 switch cc.Protocol { 79 case "direct": 80 return direct.NewTCPClient(cc.Name, dialer), nil 81 case "none", "plain": 82 return direct.NewShadowsocksNoneTCPClient(cc.Name, cc.Endpoint.String(), dialer), nil 83 case "socks5": 84 return direct.NewSocks5TCPClient(cc.Name, cc.Endpoint.String(), dialer), nil 85 case "http": 86 return http.NewProxyClient(cc.Name, cc.Endpoint.String(), dialer), nil 87 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 88 if len(cc.UnsafeRequestStreamPrefix) != 0 || len(cc.UnsafeResponseStreamPrefix) != 0 { 89 cc.logger.Warn("Unsafe stream prefix taints the client", zap.String("client", cc.Name)) 90 } 91 return ss2022.NewTCPClient(cc.Name, cc.Endpoint.String(), dialer, cc.cipherConfig, cc.UnsafeRequestStreamPrefix, cc.UnsafeResponseStreamPrefix), nil 92 default: 93 return nil, fmt.Errorf("unknown protocol: %s", cc.Protocol) 94 } 95 } 96 97 func (cc *ClientConfig) UDPClient() (zerocopy.UDPClient, error) { 98 if !cc.EnableUDP { 99 return nil, errNetworkDisabled 100 } 101 102 if cc.MTU < minimumMTU { 103 return nil, ErrMTUTooSmall 104 } 105 106 var ( 107 endpointAddrPort netip.AddrPort 108 err error 109 ) 110 111 // Resolve endpoint address for some protocols. 112 switch cc.Protocol { 113 case "none", "plain", "socks5", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 114 endpointAddrPort, err = cc.Endpoint.ResolveIPPort() 115 if err != nil { 116 return nil, err 117 } 118 } 119 120 listenConfig := cc.listenConfigCache.Get(conn.ListenerSocketOptions{ 121 Fwmark: cc.DialerFwmark, 122 TrafficClass: cc.DialerTrafficClass, 123 PathMTUDiscovery: true, 124 }) 125 126 switch cc.Protocol { 127 case "direct": 128 return direct.NewUDPClient(cc.Name, cc.MTU, listenConfig), nil 129 case "none", "plain": 130 return direct.NewShadowsocksNoneUDPClient(endpointAddrPort, cc.Name, cc.MTU, listenConfig), nil 131 case "socks5": 132 return direct.NewSocks5UDPClient(endpointAddrPort, cc.Name, cc.MTU, listenConfig), nil 133 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 134 shouldPad, err := ss2022.ParsePaddingPolicy(cc.PaddingPolicy) 135 if err != nil { 136 return nil, err 137 } 138 return ss2022.NewUDPClient(endpointAddrPort, cc.Name, cc.MTU, listenConfig, cc.cipherConfig, shouldPad), nil 139 default: 140 return nil, fmt.Errorf("unknown protocol: %s", cc.Protocol) 141 } 142 }