github.com/database64128/shadowsocks-go@v1.7.0/service/server.go (about) 1 package service 2 3 import ( 4 "fmt" 5 "time" 6 7 v1 "github.com/database64128/shadowsocks-go/api/v1" 8 "github.com/database64128/shadowsocks-go/conn" 9 "github.com/database64128/shadowsocks-go/cred" 10 "github.com/database64128/shadowsocks-go/direct" 11 "github.com/database64128/shadowsocks-go/http" 12 "github.com/database64128/shadowsocks-go/router" 13 "github.com/database64128/shadowsocks-go/ss2022" 14 "github.com/database64128/shadowsocks-go/stats" 15 "github.com/database64128/shadowsocks-go/zerocopy" 16 "github.com/database64128/tfo-go/v2" 17 "go.uber.org/zap" 18 ) 19 20 // ServerConfig stores a server configuration. 21 // It may be marshaled as or unmarshaled from JSON. 22 type ServerConfig struct { 23 Name string `json:"name"` 24 Listen string `json:"listen"` 25 Protocol string `json:"protocol"` 26 ListenerFwmark int `json:"listenerFwmark"` 27 ListenerTrafficClass int `json:"listenerTrafficClass"` 28 29 // TCP 30 EnableTCP bool `json:"enableTCP"` 31 ListenerTFO bool `json:"listenerTFO"` 32 DisableInitialPayloadWait bool `json:"disableInitialPayloadWait"` 33 34 // UDP 35 EnableUDP bool `json:"enableUDP"` 36 MTU int `json:"mtu"` 37 NatTimeoutSec int `json:"natTimeoutSec"` 38 39 // UDP performance tuning 40 UDPBatchMode string `json:"udpBatchMode"` 41 UDPRelayBatchSize int `json:"udpRelayBatchSize"` 42 UDPServerRecvBatchSize int `json:"udpServerRecvBatchSize"` 43 UDPSendChannelCapacity int `json:"udpSendChannelCapacity"` 44 45 // Simple tunnel 46 TunnelRemoteAddress conn.Addr `json:"tunnelRemoteAddress"` 47 TunnelUDPTargetOnly bool `json:"tunnelUDPTargetOnly"` 48 49 // Shadowsocks 50 PSK []byte `json:"psk"` 51 UPSKStorePath string `json:"uPSKStorePath"` 52 PaddingPolicy string `json:"paddingPolicy"` 53 RejectPolicy string `json:"rejectPolicy"` 54 userCipherConfig ss2022.UserCipherConfig 55 identityCipherConfig ss2022.ServerIdentityCipherConfig 56 tcpCredStore *ss2022.CredStore 57 udpCredStore *ss2022.CredStore 58 59 // Taint 60 UnsafeFallbackAddress *conn.Addr `json:"unsafeFallbackAddress"` 61 UnsafeRequestStreamPrefix []byte `json:"unsafeRequestStreamPrefix"` 62 UnsafeResponseStreamPrefix []byte `json:"unsafeResponseStreamPrefix"` 63 64 listenConfigCache conn.ListenConfigCache 65 collector stats.Collector 66 router *router.Router 67 logger *zap.Logger 68 index int 69 } 70 71 // Initialize initializes the server configuration. 72 func (sc *ServerConfig) Initialize(listenConfigCache conn.ListenConfigCache, collector stats.Collector, router *router.Router, logger *zap.Logger, index int) error { 73 switch sc.Protocol { 74 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 75 err := ss2022.CheckPSKLength(sc.Protocol, sc.PSK, nil) 76 if err != nil { 77 return err 78 } 79 80 if sc.UPSKStorePath == "" { 81 sc.userCipherConfig, err = ss2022.NewUserCipherConfig(sc.PSK, sc.EnableUDP) 82 if err != nil { 83 return err 84 } 85 } else { 86 sc.identityCipherConfig, err = ss2022.NewServerIdentityCipherConfig(sc.PSK, sc.EnableUDP) 87 if err != nil { 88 return err 89 } 90 } 91 } 92 93 sc.listenConfigCache = listenConfigCache 94 sc.collector = collector 95 sc.router = router 96 sc.logger = logger 97 sc.index = index 98 return nil 99 } 100 101 // TCPRelay creates a TCP relay service from the ServerConfig. 102 func (sc *ServerConfig) TCPRelay() (*TCPRelay, error) { 103 if !sc.EnableTCP && sc.Protocol != "socks5" { 104 return nil, errNetworkDisabled 105 } 106 107 var ( 108 server zerocopy.TCPServer 109 connCloser zerocopy.TCPConnCloser 110 err error 111 listenerTransparent bool 112 ) 113 114 switch sc.Protocol { 115 case "direct": 116 server = direct.NewTCPServer(sc.TunnelRemoteAddress) 117 118 case "tproxy": 119 server, err = direct.NewTCPTransparentServer() 120 if err != nil { 121 return nil, err 122 } 123 listenerTransparent = true 124 125 case "none", "plain": 126 server = direct.NewShadowsocksNoneTCPServer() 127 128 case "socks5": 129 server = direct.NewSocks5TCPServer(sc.EnableTCP, sc.EnableUDP) 130 131 case "http": 132 server = http.NewProxyServer(sc.logger) 133 134 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 135 if len(sc.UnsafeRequestStreamPrefix) != 0 || len(sc.UnsafeResponseStreamPrefix) != 0 { 136 sc.logger.Warn("Unsafe stream prefix taints the server", zap.String("server", sc.Name)) 137 } 138 139 s := ss2022.NewTCPServer(sc.userCipherConfig, sc.identityCipherConfig, sc.UnsafeRequestStreamPrefix, sc.UnsafeResponseStreamPrefix) 140 sc.tcpCredStore = &s.CredStore 141 server = s 142 143 default: 144 return nil, fmt.Errorf("invalid protocol: %s", sc.Protocol) 145 } 146 147 serverInfo := server.Info() 148 149 connCloser, err = zerocopy.ParseRejectPolicy(sc.RejectPolicy, serverInfo.DefaultTCPConnCloser) 150 if err != nil { 151 return nil, err 152 } 153 154 if sc.UnsafeFallbackAddress != nil { 155 sc.logger.Warn("Unsafe fallback taints the server", 156 zap.String("server", sc.Name), 157 zap.Stringer("fallbackAddress", sc.UnsafeFallbackAddress), 158 ) 159 } 160 161 waitForInitialPayload := !serverInfo.NativeInitialPayload && !sc.DisableInitialPayloadWait 162 163 listenConfig := sc.listenConfigCache.Get(conn.ListenerSocketOptions{ 164 Fwmark: sc.ListenerFwmark, 165 TrafficClass: sc.ListenerTrafficClass, 166 Transparent: listenerTransparent, 167 TCPFastOpen: sc.ListenerTFO, 168 }) 169 170 return NewTCPRelay(sc.index, sc.Name, sc.Listen, waitForInitialPayload, listenConfig, server, connCloser, sc.UnsafeFallbackAddress, sc.collector, sc.router, sc.logger), nil 171 } 172 173 // UDPRelay creates a UDP relay service from the ServerConfig. 174 func (sc *ServerConfig) UDPRelay(maxClientPackerHeadroom zerocopy.Headroom) (Relay, error) { 175 if !sc.EnableUDP { 176 return nil, errNetworkDisabled 177 } 178 179 if sc.MTU < minimumMTU { 180 return nil, ErrMTUTooSmall 181 } 182 183 switch sc.UDPBatchMode { 184 case "", "no", "sendmmsg": 185 default: 186 return nil, fmt.Errorf("unknown UDP batch mode: %s", sc.UDPBatchMode) 187 } 188 189 switch { 190 case sc.UDPRelayBatchSize > 0 && sc.UDPRelayBatchSize <= 1024: 191 case sc.UDPRelayBatchSize == 0: 192 sc.UDPRelayBatchSize = defaultRelayBatchSize 193 default: 194 return nil, fmt.Errorf("UDP relay batch size out of range [0, 1024]: %d", sc.UDPRelayBatchSize) 195 } 196 197 switch { 198 case sc.UDPServerRecvBatchSize > 0 && sc.UDPServerRecvBatchSize <= 1024: 199 case sc.UDPServerRecvBatchSize == 0: 200 sc.UDPServerRecvBatchSize = defaultServerRecvBatchSize 201 default: 202 return nil, fmt.Errorf("UDP server recv batch size out of range [0, 1024]: %d", sc.UDPServerRecvBatchSize) 203 } 204 205 switch { 206 case sc.UDPSendChannelCapacity >= 64: 207 case sc.UDPSendChannelCapacity == 0: 208 sc.UDPSendChannelCapacity = defaultSendChannelCapacity 209 default: 210 return nil, fmt.Errorf("UDP send channel capacity must be at least 64: %d", sc.UDPSendChannelCapacity) 211 } 212 213 var ( 214 natTimeout time.Duration 215 natServer zerocopy.UDPNATServer 216 server zerocopy.UDPSessionServer 217 serverConnListenConfig tfo.ListenConfig 218 transparentConnListenConfig tfo.ListenConfig 219 ) 220 221 switch { 222 case sc.NatTimeoutSec == 0: 223 natTimeout = defaultNatTimeout 224 case sc.NatTimeoutSec < minNatTimeoutSec: 225 return nil, fmt.Errorf("natTimeoutSec too short: %d, must be at least %d", sc.NatTimeoutSec, minNatTimeoutSec) 226 default: 227 natTimeout = time.Duration(sc.NatTimeoutSec) * time.Second 228 } 229 230 switch sc.Protocol { 231 case "direct": 232 natServer = direct.NewDirectUDPNATServer(sc.TunnelRemoteAddress, sc.TunnelUDPTargetOnly) 233 234 case "tproxy": 235 236 case "none", "plain": 237 natServer = direct.ShadowsocksNoneUDPNATServer{} 238 239 case "socks5": 240 natServer = direct.Socks5UDPNATServer{} 241 242 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 243 shouldPad, err := ss2022.ParsePaddingPolicy(sc.PaddingPolicy) 244 if err != nil { 245 return nil, err 246 } 247 248 s := ss2022.NewUDPServer(sc.userCipherConfig, sc.identityCipherConfig, shouldPad) 249 sc.udpCredStore = &s.CredStore 250 server = s 251 252 default: 253 return nil, fmt.Errorf("invalid protocol: %s", sc.Protocol) 254 } 255 256 switch sc.Protocol { 257 case "tproxy": 258 serverConnListenConfig = sc.listenConfigCache.Get(conn.ListenerSocketOptions{ 259 Fwmark: sc.ListenerFwmark, 260 TrafficClass: sc.ListenerTrafficClass, 261 Transparent: true, 262 PathMTUDiscovery: true, 263 ReceiveOriginalDestAddr: true, 264 }) 265 transparentConnListenConfig = sc.listenConfigCache.Get(conn.ListenerSocketOptions{ 266 Fwmark: sc.ListenerFwmark, 267 TrafficClass: sc.ListenerTrafficClass, 268 Transparent: true, 269 ReusePort: true, 270 PathMTUDiscovery: true, 271 }) 272 default: 273 serverConnListenConfig = sc.listenConfigCache.Get(conn.ListenerSocketOptions{ 274 Fwmark: sc.ListenerFwmark, 275 TrafficClass: sc.ListenerTrafficClass, 276 PathMTUDiscovery: true, 277 ReceivePacketInfo: true, 278 }) 279 } 280 281 switch sc.Protocol { 282 case "direct", "none", "plain", "socks5": 283 return NewUDPNATRelay(sc.UDPBatchMode, sc.Name, sc.Listen, sc.UDPRelayBatchSize, sc.UDPServerRecvBatchSize, sc.UDPSendChannelCapacity, sc.index, sc.MTU, maxClientPackerHeadroom, natTimeout, natServer, serverConnListenConfig, sc.collector, sc.router, sc.logger), nil 284 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 285 return NewUDPSessionRelay(sc.UDPBatchMode, sc.Name, sc.Listen, sc.UDPRelayBatchSize, sc.UDPServerRecvBatchSize, sc.UDPSendChannelCapacity, sc.index, sc.MTU, maxClientPackerHeadroom, natTimeout, server, serverConnListenConfig, sc.collector, sc.router, sc.logger), nil 286 case "tproxy": 287 return NewUDPTransparentRelay(sc.Name, sc.Listen, sc.UDPRelayBatchSize, sc.UDPServerRecvBatchSize, sc.UDPSendChannelCapacity, sc.index, sc.MTU, maxClientPackerHeadroom, natTimeout, serverConnListenConfig, transparentConnListenConfig, sc.collector, sc.router, sc.logger) 288 default: 289 return nil, fmt.Errorf("invalid protocol: %s", sc.Protocol) 290 } 291 } 292 293 // PostInit performs post-initialization tasks. 294 func (sc *ServerConfig) PostInit(credman *cred.Manager, apiSM *v1.ServerManager) error { 295 var cms *cred.ManagedServer 296 297 switch sc.Protocol { 298 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 299 if sc.UPSKStorePath != "" { 300 var err error 301 cms, err = credman.RegisterServer(sc.Name, sc.UPSKStorePath, len(sc.PSK), sc.tcpCredStore, sc.udpCredStore) 302 if err != nil { 303 return err 304 } 305 } 306 } 307 308 if apiSM != nil { 309 apiSM.AddServer(sc.Name, cms, sc.collector) 310 } 311 312 return nil 313 }