github.com/database64128/shadowsocks-go@v1.10.2-0.20240315062903-143a773533f1/service/server.go (about) 1 package service 2 3 import ( 4 "errors" 5 "fmt" 6 "net/netip" 7 "time" 8 9 v1 "github.com/database64128/shadowsocks-go/api/v1" 10 "github.com/database64128/shadowsocks-go/conn" 11 "github.com/database64128/shadowsocks-go/cred" 12 "github.com/database64128/shadowsocks-go/direct" 13 "github.com/database64128/shadowsocks-go/http" 14 "github.com/database64128/shadowsocks-go/jsonhelper" 15 "github.com/database64128/shadowsocks-go/router" 16 "github.com/database64128/shadowsocks-go/ss2022" 17 "github.com/database64128/shadowsocks-go/stats" 18 "github.com/database64128/shadowsocks-go/zerocopy" 19 "go.uber.org/zap" 20 ) 21 22 // ListenerConfig is the shared part of TCP listener and UDP server socket configurations. 23 type ListenerConfig struct { 24 // Network is the network type. 25 // Valid values include "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6". 26 Network string `json:"network"` 27 28 // Address is the address to listen on. 29 Address string `json:"address"` 30 31 // Fwmark sets the listener's fwmark on Linux, or user cookie on FreeBSD. 32 // 33 // Available on Linux and FreeBSD. 34 Fwmark int `json:"fwmark"` 35 36 // TrafficClass sets the traffic class of the listener. 37 // 38 // Available on most platforms except Windows. 39 TrafficClass int `json:"trafficClass"` 40 41 // ReusePort enables SO_REUSEPORT on the listener. 42 // 43 // Available on Linux and the BSDs. 44 ReusePort bool `json:"reusePort"` 45 } 46 47 // TCPListenerConfig is the configuration for a TCP listener. 48 type TCPListenerConfig struct { 49 // ListenerConfig is the shared part of TCP listener and UDP server socket configurations. 50 ListenerConfig 51 52 // FastOpen enables TCP Fast Open on the listener. 53 // 54 // Available on Linux, macOS, FreeBSD, and Windows. 55 FastOpen bool `json:"fastOpen"` 56 57 // FastOpenFallback enables runtime detection of TCP Fast Open support on the listener. 58 // 59 // When enabled, the listener will start without TFO if TFO is not available on the system. 60 // When disabled, the listener will abort if TFO cannot be enabled on the socket. 61 // 62 // Available on all platforms. 63 FastOpenFallback bool `json:"fastOpenFallback"` 64 65 // Multipath enables multipath TCP on the listener. 66 // 67 // Unlike Go std, we make MPTCP strictly opt-in. 68 // That is, if this field is false, MPTCP will be explicitly disabled. 69 // This ensures that if Go std suddenly decides to enable MPTCP by default, 70 // existing configurations won't encounter issues due to missing features in the kernel MPTCP stack, 71 // such as TCP keepalive (as of Linux 6.5), and failed connect attempts won't always be retried once. 72 // 73 // Available on platforms supported by Go std's MPTCP implementation. 74 Multipath bool `json:"multipath"` 75 76 // DisableInitialPayloadWait disables the brief wait for initial payload. 77 // Setting it to true is useful when the listener only relays server-speaks-first protocols. 78 DisableInitialPayloadWait bool `json:"disableInitialPayloadWait"` 79 80 // InitialPayloadWaitTimeout is the read timeout when waiting for the initial payload. 81 // 82 // The default value is 250ms. 83 InitialPayloadWaitTimeout jsonhelper.Duration `json:"initialPayloadWaitTimeout"` 84 85 // InitialPayloadWaitBufferSize is the read buffer size when waiting for the initial payload. 86 // 87 // The default value is 1440. 88 InitialPayloadWaitBufferSize int `json:"initialPayloadWaitBufferSize"` 89 90 // FastOpenBacklog specifies the maximum number of pending TFO connections on Linux. 91 // If the value is 0, Go std's listen(2) backlog is used. 92 // 93 // On other platforms, a non-negative value is ignored, as they do not have the option to set the TFO backlog. 94 // 95 // On all platforms, a negative value disables TFO. 96 FastOpenBacklog int `json:"fastOpenBacklog"` 97 } 98 99 // Configure returns a TCP listener configuration. 100 func (lnc *TCPListenerConfig) Configure(listenConfigCache conn.ListenConfigCache, transparent, serverNativeInitialPayload bool) (tcpRelayListener, error) { 101 switch lnc.Network { 102 case "tcp", "tcp4", "tcp6": 103 default: 104 return tcpRelayListener{}, fmt.Errorf("invalid network: %s", lnc.Network) 105 } 106 107 initialPayloadWaitTimeout := time.Duration(lnc.InitialPayloadWaitTimeout) 108 109 switch { 110 case initialPayloadWaitTimeout == 0: 111 initialPayloadWaitTimeout = defaultInitialPayloadWaitTimeout 112 case initialPayloadWaitTimeout < 0: 113 return tcpRelayListener{}, fmt.Errorf("negative initial payload wait timeout: %s", initialPayloadWaitTimeout) 114 } 115 116 switch { 117 case lnc.InitialPayloadWaitBufferSize == 0: 118 lnc.InitialPayloadWaitBufferSize = defaultInitialPayloadWaitBufferSize 119 case lnc.InitialPayloadWaitBufferSize < 0: 120 return tcpRelayListener{}, fmt.Errorf("negative initial payload wait buffer size: %d", lnc.InitialPayloadWaitBufferSize) 121 } 122 123 return tcpRelayListener{ 124 listenConfig: listenConfigCache.Get(conn.ListenerSocketOptions{ 125 Fwmark: lnc.Fwmark, 126 TrafficClass: lnc.TrafficClass, 127 TCPFastOpenBacklog: lnc.FastOpenBacklog, 128 ReusePort: lnc.ReusePort, 129 Transparent: transparent, 130 TCPFastOpen: lnc.FastOpen, 131 TCPFastOpenFallback: lnc.FastOpenFallback, 132 MultipathTCP: lnc.Multipath, 133 }), 134 waitForInitialPayload: !serverNativeInitialPayload && !lnc.DisableInitialPayloadWait, 135 initialPayloadWaitTimeout: initialPayloadWaitTimeout, 136 initialPayloadWaitBufferSize: lnc.InitialPayloadWaitBufferSize, 137 network: lnc.Network, 138 address: lnc.Address, 139 }, nil 140 } 141 142 // UDPListenerConfig is the configuration for a UDP server socket. 143 type UDPListenerConfig struct { 144 // ListenerConfig is the shared part of TCP listener and UDP server socket configurations. 145 ListenerConfig 146 147 // UDPPerfConfig exposes performance tuning options. 148 UDPPerfConfig 149 150 // NATTimeout is the duration after which an inactive NAT mapping expires. 151 // 152 // The default value is 5 minutes. 153 NATTimeout jsonhelper.Duration `json:"natTimeout"` 154 } 155 156 // Configure returns a UDP server socket configuration. 157 func (lnc *UDPListenerConfig) Configure(listenConfigCache conn.ListenConfigCache, minNATTimeout time.Duration, transparent bool) (udpRelayServerConn, error) { 158 switch lnc.Network { 159 case "udp", "udp4", "udp6": 160 default: 161 return udpRelayServerConn{}, fmt.Errorf("invalid network: %s", lnc.Network) 162 } 163 164 if err := lnc.UDPPerfConfig.CheckAndApplyDefaults(); err != nil { 165 return udpRelayServerConn{}, err 166 } 167 168 natTimeout := time.Duration(lnc.NATTimeout) 169 170 switch { 171 case natTimeout == 0: 172 natTimeout = defaultNatTimeout 173 case natTimeout < minNATTimeout: 174 return udpRelayServerConn{}, fmt.Errorf("NAT timeout %s is less than server's minimum NAT timeout %s", natTimeout, minNATTimeout) 175 } 176 177 return udpRelayServerConn{ 178 listenConfig: listenConfigCache.Get(conn.ListenerSocketOptions{ 179 Fwmark: lnc.Fwmark, 180 TrafficClass: lnc.TrafficClass, 181 ReusePort: lnc.ReusePort, 182 Transparent: transparent, 183 PathMTUDiscovery: true, 184 ReceivePacketInfo: true, 185 }), 186 network: lnc.Network, 187 address: lnc.Address, 188 batchMode: lnc.UDPPerfConfig.BatchMode, 189 relayBatchSize: lnc.UDPPerfConfig.RelayBatchSize, 190 serverRecvBatchSize: lnc.UDPPerfConfig.ServerRecvBatchSize, 191 sendChannelCapacity: lnc.UDPPerfConfig.SendChannelCapacity, 192 natTimeout: natTimeout, 193 }, nil 194 } 195 196 // ServerConfig stores a server configuration. 197 // It may be marshaled as or unmarshaled from JSON. 198 type ServerConfig struct { 199 // Name is the name of the server. 200 Name string `json:"name"` 201 202 // Protocol is the protocol the server uses. 203 // Valid values include "direct", "tproxy" (Linux only), "socks5", "http", "none", "plain", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm". 204 Protocol string `json:"protocol"` 205 206 // TCPListeners is the list of TCP listeners. 207 TCPListeners []TCPListenerConfig `json:"tcpListeners"` 208 209 // UDPListeners is the list of UDP listeners. 210 UDPListeners []UDPListenerConfig `json:"udpListeners"` 211 212 // MTU is the MTU of the server's designated network path. 213 // The value is used for calculating UDP receive buffer size. 214 MTU int `json:"mtu"` 215 216 // Single listener configuration. 217 218 Listen string `json:"listen"` 219 ListenerFwmark int `json:"listenerFwmark"` 220 ListenerTrafficClass int `json:"listenerTrafficClass"` 221 222 // TCP 223 224 EnableTCP bool `json:"enableTCP"` 225 ListenerTFO bool `json:"listenerTFO"` 226 DisableInitialPayloadWait bool `json:"disableInitialPayloadWait"` 227 228 // UDP 229 230 EnableUDP bool `json:"enableUDP"` 231 NatTimeoutSec int `json:"natTimeoutSec"` 232 233 // UDP performance tuning 234 235 UDPBatchMode string `json:"udpBatchMode"` 236 UDPRelayBatchSize int `json:"udpRelayBatchSize"` 237 UDPServerRecvBatchSize int `json:"udpServerRecvBatchSize"` 238 UDPSendChannelCapacity int `json:"udpSendChannelCapacity"` 239 240 // Simple tunnel 241 242 TunnelRemoteAddress conn.Addr `json:"tunnelRemoteAddress"` 243 TunnelUDPTargetOnly bool `json:"tunnelUDPTargetOnly"` 244 245 tcpEnabled bool 246 udpEnabled bool 247 248 // AllowSegmentedFixedLengthHeader disables the requirement that 249 // the fixed-length header must be read in a single read call. 250 // 251 // This option is useful when the underlying stream transport 252 // does not exhibit typical TCP behavior. 253 // 254 // Only applicable to Shadowsocks 2022 TCP. 255 AllowSegmentedFixedLengthHeader bool `json:"allowSegmentedFixedLengthHeader"` 256 257 // Shadowsocks 258 259 PSK []byte `json:"psk"` 260 UPSKStorePath string `json:"uPSKStorePath"` 261 PaddingPolicy string `json:"paddingPolicy"` 262 RejectPolicy string `json:"rejectPolicy"` 263 264 // SlidingWindowFilterSize is the size of the sliding window filter. 265 // 266 // The default value is 256. 267 // 268 // Only applicable to Shadowsocks 2022 UDP. 269 SlidingWindowFilterSize int `json:"slidingWindowFilterSize"` 270 271 userCipherConfig ss2022.UserCipherConfig 272 identityCipherConfig ss2022.ServerIdentityCipherConfig 273 tcpCredStore *ss2022.CredStore 274 udpCredStore *ss2022.CredStore 275 276 // Taint 277 278 UnsafeFallbackAddress conn.Addr `json:"unsafeFallbackAddress"` 279 UnsafeRequestStreamPrefix []byte `json:"unsafeRequestStreamPrefix"` 280 UnsafeResponseStreamPrefix []byte `json:"unsafeResponseStreamPrefix"` 281 282 listenConfigCache conn.ListenConfigCache 283 collector stats.Collector 284 router *router.Router 285 logger *zap.Logger 286 index int 287 } 288 289 // Initialize initializes the server configuration. 290 func (sc *ServerConfig) Initialize(listenConfigCache conn.ListenConfigCache, collector stats.Collector, router *router.Router, logger *zap.Logger, index int) error { 291 sc.tcpEnabled = sc.EnableTCP || len(sc.TCPListeners) > 0 292 sc.udpEnabled = sc.EnableUDP || len(sc.UDPListeners) > 0 293 294 switch sc.Protocol { 295 case "direct": 296 if !sc.TunnelRemoteAddress.IsValid() { 297 return errors.New("tunnelRemoteAddress is required for simple tunnel") 298 } 299 300 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 301 err := ss2022.CheckPSKLength(sc.Protocol, sc.PSK, nil) 302 if err != nil { 303 return err 304 } 305 306 if sc.UPSKStorePath == "" { 307 sc.userCipherConfig, err = ss2022.NewUserCipherConfig(sc.PSK, sc.udpEnabled) 308 if err != nil { 309 return err 310 } 311 } else { 312 sc.identityCipherConfig, err = ss2022.NewServerIdentityCipherConfig(sc.PSK, sc.udpEnabled) 313 if err != nil { 314 return err 315 } 316 } 317 } 318 319 if sc.EnableTCP { 320 sc.TCPListeners = append(sc.TCPListeners, TCPListenerConfig{ 321 ListenerConfig: ListenerConfig{ 322 Network: "tcp", 323 Address: sc.Listen, 324 Fwmark: sc.ListenerFwmark, 325 TrafficClass: sc.ListenerTrafficClass, 326 }, 327 FastOpen: sc.ListenerTFO, 328 DisableInitialPayloadWait: sc.DisableInitialPayloadWait, 329 }) 330 } 331 332 if sc.EnableUDP { 333 sc.UDPListeners = append(sc.UDPListeners, UDPListenerConfig{ 334 ListenerConfig: ListenerConfig{ 335 Network: "udp", 336 Address: sc.Listen, 337 Fwmark: sc.ListenerFwmark, 338 TrafficClass: sc.ListenerTrafficClass, 339 }, 340 UDPPerfConfig: UDPPerfConfig{ 341 BatchMode: sc.UDPBatchMode, 342 RelayBatchSize: sc.UDPRelayBatchSize, 343 ServerRecvBatchSize: sc.UDPServerRecvBatchSize, 344 SendChannelCapacity: sc.UDPSendChannelCapacity, 345 }, 346 NATTimeout: jsonhelper.Duration(time.Duration(sc.NatTimeoutSec) * time.Second), 347 }) 348 } 349 350 sc.listenConfigCache = listenConfigCache 351 sc.collector = collector 352 sc.router = router 353 sc.logger = logger 354 sc.index = index 355 return nil 356 } 357 358 // TCPRelay creates a TCP relay service from the ServerConfig. 359 func (sc *ServerConfig) TCPRelay() (*TCPRelay, error) { 360 if len(sc.TCPListeners) == 0 { 361 return nil, errNetworkDisabled 362 } 363 364 var ( 365 server zerocopy.TCPServer 366 connCloser zerocopy.TCPConnCloser 367 err error 368 listenerTransparent bool 369 ) 370 371 switch sc.Protocol { 372 case "direct": 373 server = direct.NewTCPServer(sc.TunnelRemoteAddress) 374 375 case "tproxy": 376 server, err = direct.NewTCPTransparentServer() 377 if err != nil { 378 return nil, err 379 } 380 listenerTransparent = true 381 382 case "none", "plain": 383 server = direct.NewShadowsocksNoneTCPServer() 384 385 case "socks5": 386 server = direct.NewSocks5TCPServer(sc.tcpEnabled, sc.udpEnabled) 387 388 case "http": 389 server = http.NewProxyServer(sc.logger) 390 391 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 392 if len(sc.UnsafeRequestStreamPrefix) != 0 || len(sc.UnsafeResponseStreamPrefix) != 0 { 393 sc.logger.Warn("Unsafe stream prefix taints the server", zap.String("server", sc.Name)) 394 } 395 396 s := ss2022.NewTCPServer(sc.AllowSegmentedFixedLengthHeader, sc.userCipherConfig, sc.identityCipherConfig, sc.UnsafeRequestStreamPrefix, sc.UnsafeResponseStreamPrefix) 397 sc.tcpCredStore = &s.CredStore 398 server = s 399 400 default: 401 return nil, fmt.Errorf("invalid protocol: %s", sc.Protocol) 402 } 403 404 serverInfo := server.Info() 405 406 connCloser, err = zerocopy.ParseRejectPolicy(sc.RejectPolicy, serverInfo.DefaultTCPConnCloser) 407 if err != nil { 408 return nil, err 409 } 410 411 if sc.UnsafeFallbackAddress.IsValid() { 412 sc.logger.Warn("Unsafe fallback taints the server", 413 zap.String("server", sc.Name), 414 zap.Stringer("fallbackAddress", sc.UnsafeFallbackAddress), 415 ) 416 } 417 418 listeners := make([]tcpRelayListener, len(sc.TCPListeners)) 419 420 for i := range listeners { 421 listeners[i], err = sc.TCPListeners[i].Configure(sc.listenConfigCache, listenerTransparent, serverInfo.NativeInitialPayload) 422 if err != nil { 423 return nil, err 424 } 425 } 426 427 return NewTCPRelay(sc.index, sc.Name, listeners, server, connCloser, sc.UnsafeFallbackAddress, sc.collector, sc.router, sc.logger), nil 428 } 429 430 // UDPRelay creates a UDP relay service from the ServerConfig. 431 func (sc *ServerConfig) UDPRelay(maxClientPackerHeadroom zerocopy.Headroom) (Relay, error) { 432 if len(sc.UDPListeners) == 0 { 433 return nil, errNetworkDisabled 434 } 435 436 if sc.MTU < minimumMTU { 437 return nil, ErrMTUTooSmall 438 } 439 440 var ( 441 natServer zerocopy.UDPNATServer 442 sessionServer zerocopy.UDPSessionServer 443 serverUnpackerHeadroom zerocopy.Headroom 444 transparentConnListenConfig conn.ListenConfig 445 minNATTimeout time.Duration 446 err error 447 listenerTransparent bool 448 ) 449 450 switch sc.Protocol { 451 case "direct": 452 natServer = direct.NewDirectUDPNATServer(sc.TunnelRemoteAddress, sc.TunnelUDPTargetOnly) 453 454 case "tproxy": 455 transparentConnListenConfig = sc.listenConfigCache.Get(conn.ListenerSocketOptions{ 456 Fwmark: sc.ListenerFwmark, 457 TrafficClass: sc.ListenerTrafficClass, 458 Transparent: true, 459 ReusePort: true, 460 PathMTUDiscovery: true, 461 }) 462 listenerTransparent = true 463 464 case "none", "plain": 465 natServer = direct.ShadowsocksNoneUDPNATServer{} 466 467 case "socks5": 468 natServer = direct.Socks5UDPNATServer{} 469 470 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 471 shouldPad, err := ss2022.ParsePaddingPolicy(sc.PaddingPolicy) 472 if err != nil { 473 return nil, err 474 } 475 476 switch { 477 case sc.SlidingWindowFilterSize == 0: 478 sc.SlidingWindowFilterSize = ss2022.DefaultSlidingWindowFilterSize 479 case sc.SlidingWindowFilterSize < 0: 480 return nil, fmt.Errorf("negative sliding window filter size: %d", sc.SlidingWindowFilterSize) 481 } 482 483 s := ss2022.NewUDPServer(uint64(sc.SlidingWindowFilterSize), sc.userCipherConfig, sc.identityCipherConfig, shouldPad) 484 sc.udpCredStore = &s.CredStore 485 sessionServer = s 486 487 default: 488 return nil, fmt.Errorf("invalid protocol: %s", sc.Protocol) 489 } 490 491 switch sc.Protocol { 492 case "direct", "none", "plain", "socks5": 493 serverUnpackerHeadroom = natServer.Info().UnpackerHeadroom 494 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 495 info := sessionServer.Info() 496 serverUnpackerHeadroom = info.UnpackerHeadroom 497 minNATTimeout = info.MinNATTimeout 498 } 499 500 packetBufHeadroom := zerocopy.UDPRelayHeadroom(maxClientPackerHeadroom, serverUnpackerHeadroom) 501 packetBufRecvSize := zerocopy.MaxPacketSizeForAddr(sc.MTU, netip.IPv4Unspecified()) 502 packetBufSize := packetBufHeadroom.Front + packetBufRecvSize + packetBufHeadroom.Rear 503 504 listeners := make([]udpRelayServerConn, len(sc.UDPListeners)) 505 506 for i := range listeners { 507 listeners[i], err = sc.UDPListeners[i].Configure(sc.listenConfigCache, minNATTimeout, listenerTransparent) 508 if err != nil { 509 return nil, err 510 } 511 } 512 513 switch sc.Protocol { 514 case "direct", "none", "plain", "socks5": 515 return NewUDPNATRelay(sc.Name, sc.index, sc.MTU, packetBufHeadroom.Front, packetBufRecvSize, packetBufSize, listeners, natServer, sc.collector, sc.router, sc.logger), nil 516 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 517 return NewUDPSessionRelay(sc.Name, sc.index, sc.MTU, packetBufHeadroom.Front, packetBufRecvSize, packetBufSize, listeners, sessionServer, sc.collector, sc.router, sc.logger), nil 518 case "tproxy": 519 return NewUDPTransparentRelay(sc.Name, sc.index, sc.MTU, packetBufHeadroom.Front, packetBufRecvSize, packetBufSize, listeners, transparentConnListenConfig, sc.collector, sc.router, sc.logger) 520 default: 521 return nil, fmt.Errorf("invalid protocol: %s", sc.Protocol) 522 } 523 } 524 525 // PostInit performs post-initialization tasks. 526 func (sc *ServerConfig) PostInit(credman *cred.Manager, apiSM *v1.ServerManager) error { 527 var cms *cred.ManagedServer 528 529 switch sc.Protocol { 530 case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 531 if sc.UPSKStorePath != "" { 532 var err error 533 cms, err = credman.RegisterServer(sc.Name, sc.UPSKStorePath, len(sc.PSK), sc.tcpCredStore, sc.udpCredStore) 534 if err != nil { 535 return err 536 } 537 } 538 } 539 540 if apiSM != nil { 541 apiSM.AddServer(sc.Name, cms, sc.collector) 542 } 543 544 return nil 545 }