2024-11-02 00:39:02 +08:00
package tun
2022-07-09 19:18:37 +08:00
import (
"context"
"net"
2024-06-07 15:55:21 +08:00
"net/netip"
"os"
"runtime"
2022-07-09 19:18:37 +08:00
"strconv"
"strings"
2023-12-20 19:55:14 +08:00
"time"
2022-07-09 19:18:37 +08:00
"github.com/sagernet/sing-box/adapter"
2024-11-02 00:39:02 +08:00
"github.com/sagernet/sing-box/adapter/inbound"
2023-12-04 11:47:25 +08:00
"github.com/sagernet/sing-box/common/taskmonitor"
2022-07-09 19:18:37 +08:00
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
2025-02-17 22:00:57 +08:00
"github.com/sagernet/sing-box/route/rule"
2022-07-11 18:44:59 +08:00
"github.com/sagernet/sing-tun"
2022-07-13 19:01:20 +08:00
"github.com/sagernet/sing/common"
2022-07-09 19:18:37 +08:00
E "github.com/sagernet/sing/common/exceptions"
2024-11-18 18:55:34 +08:00
"github.com/sagernet/sing/common/json/badoption"
2022-07-09 19:18:37 +08:00
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
2022-08-15 00:25:49 +08:00
"github.com/sagernet/sing/common/ranges"
2024-06-07 15:55:21 +08:00
"github.com/sagernet/sing/common/x/list"
2024-11-02 00:39:02 +08:00
"github.com/sagernet/sing/service"
2024-06-07 15:55:21 +08:00
"go4.org/netipx"
2022-07-09 19:18:37 +08:00
)
2024-11-02 00:39:02 +08:00
func RegisterInbound ( registry * inbound . Registry ) {
inbound . Register [ option . TunInboundOptions ]( registry , C . TypeTun , NewInbound )
}
2022-07-09 19:18:37 +08:00
2024-11-02 00:39:02 +08:00
type Inbound struct {
2026-02-28 17:55:56 +08:00
tag string
ctx context . Context
router adapter . Router
networkManager adapter . NetworkManager
logger log . ContextLogger
2024-11-23 22:34:02 +08:00
tunOptions tun . Options
2024-10-21 23:38:34 +08:00
udpTimeout time . Duration
2024-06-07 15:55:21 +08:00
stack string
tunIf tun . Tun
tunStack tun . Stack
2025-10-07 15:40:11 +08:00
platformInterface adapter . PlatformInterface
2024-06-07 15:55:21 +08:00
platformOptions option . TunPlatformOptions
autoRedirect tun . AutoRedirect
routeRuleSet [] adapter . RuleSet
routeRuleSetCallback [] * list . Element [ adapter . RuleSetUpdateCallback ]
routeExcludeRuleSet [] adapter . RuleSet
routeExcludeRuleSetCallback [] * list . Element [ adapter . RuleSetUpdateCallback ]
routeAddressSet [] * netipx . IPSet
routeExcludeAddressSet [] * netipx . IPSet
2022-07-09 19:18:37 +08:00
}
2024-11-02 00:39:02 +08:00
func NewInbound ( ctx context . Context , router adapter . Router , logger log . ContextLogger , tag string , options option . TunInboundOptions ) ( adapter . Inbound , error ) {
2024-06-07 15:55:21 +08:00
//nolint:staticcheck
2026-02-28 17:55:56 +08:00
if len ( options . Inet4Address ) > 0 || len ( options . Inet6Address ) > 0 ||
len ( options . Inet4RouteAddress ) > 0 || len ( options . Inet6RouteAddress ) > 0 ||
len ( options . Inet4RouteExcludeAddress ) > 0 || len ( options . Inet6RouteExcludeAddress ) > 0 {
return nil , E . New ( "legacy tun address fields are deprecated in sing-box 1.10.0 and removed in sing-box 1.12.0" )
2024-06-07 15:55:21 +08:00
}
//nolint:staticcheck
2026-02-28 17:55:56 +08:00
if options . GSO {
return nil , E . New ( "GSO option in tun is deprecated in sing-box 1.11.0 and removed in sing-box 1.12.0" )
2024-06-07 15:55:21 +08:00
}
2026-03-21 17:09:34 +08:00
//nolint:staticcheck
if options . InboundOptions != ( option . InboundOptions {}) {
return nil , E . New ( "legacy inbound fields are deprecated in sing-box 1.11.0 and removed in sing-box 1.13.0, checkout migration: https://sing-box.sagernet.org/migration/#migrate-legacy-inbound-fields-to-rule-actions" )
}
2026-02-28 17:55:56 +08:00
address := options . Address
2024-06-07 15:55:21 +08:00
inet4Address := common . Filter ( address , func ( it netip . Prefix ) bool {
return it . Addr (). Is4 ()
})
inet6Address := common . Filter ( address , func ( it netip . Prefix ) bool {
return it . Addr (). Is6 ()
})
routeAddress := options . RouteAddress
inet4RouteAddress := common . Filter ( routeAddress , func ( it netip . Prefix ) bool {
return it . Addr (). Is4 ()
})
inet6RouteAddress := common . Filter ( routeAddress , func ( it netip . Prefix ) bool {
return it . Addr (). Is6 ()
})
routeExcludeAddress := options . RouteExcludeAddress
inet4RouteExcludeAddress := common . Filter ( routeExcludeAddress , func ( it netip . Prefix ) bool {
return it . Addr (). Is4 ()
})
inet6RouteExcludeAddress := common . Filter ( routeExcludeAddress , func ( it netip . Prefix ) bool {
return it . Addr (). Is6 ()
})
2025-10-07 15:40:11 +08:00
platformInterface := service . FromContext [ adapter . PlatformInterface ]( ctx )
2022-07-10 09:15:01 +08:00
tunMTU := options . MTU
2025-07-12 14:47:27 +08:00
enableGSO := C . IsLinux && options . Stack == "gvisor" && platformInterface == nil && tunMTU > 0 && tunMTU < 49152
2022-07-10 09:15:01 +08:00
if tunMTU == 0 {
2025-07-02 19:22:23 +08:00
if platformInterface != nil && platformInterface . UnderNetworkExtension () {
2025-07-04 10:29:55 +08:00
// In Network Extension, when MTU exceeds 4064 (4096-UTUN_IF_HEADROOM_SIZE), the performance of tun will drop significantly, which may be a system bug.
tunMTU = 4064
2025-08-13 11:48:44 +08:00
} else if C . IsAndroid {
// Some Android devices report ENOBUFS when using MTU 65535
tunMTU = 9000
2025-07-02 19:22:23 +08:00
} else {
2025-07-12 14:47:27 +08:00
tunMTU = 65535
2025-07-02 19:22:23 +08:00
}
2022-07-10 09:15:01 +08:00
}
2023-12-20 19:55:14 +08:00
var udpTimeout time . Duration
2022-07-26 19:21:56 +08:00
if options . UDPTimeout != 0 {
2023-12-20 19:55:14 +08:00
udpTimeout = time . Duration ( options . UDPTimeout )
2022-07-26 19:21:56 +08:00
} else {
2023-12-20 19:55:14 +08:00
udpTimeout = C . UDPTimeout
2022-07-26 19:21:56 +08:00
}
2024-06-07 15:55:21 +08:00
var err error
2022-08-15 00:25:49 +08:00
includeUID := uidToRange ( options . IncludeUID )
if len ( options . IncludeUIDRange ) > 0 {
includeUID , err = parseRange ( includeUID , options . IncludeUIDRange )
if err != nil {
return nil , E . Cause ( err , "parse include_uid_range" )
}
}
excludeUID := uidToRange ( options . ExcludeUID )
if len ( options . ExcludeUIDRange ) > 0 {
excludeUID , err = parseRange ( excludeUID , options . ExcludeUIDRange )
if err != nil {
return nil , E . Cause ( err , "parse exclude_uid_range" )
}
}
2024-06-07 15:55:21 +08:00
tableIndex := options . IPRoute2TableIndex
if tableIndex == 0 {
tableIndex = tun . DefaultIPRoute2TableIndex
}
ruleIndex := options . IPRoute2RuleIndex
if ruleIndex == 0 {
ruleIndex = tun . DefaultIPRoute2RuleIndex
}
2026-01-29 12:07:15 +08:00
autoRedirectFallbackRuleIndex := options . AutoRedirectFallbackRuleIndex
if autoRedirectFallbackRuleIndex == 0 {
autoRedirectFallbackRuleIndex = tun . DefaultIPRoute2AutoRedirectFallbackRuleIndex
}
2024-06-22 14:11:49 +08:00
inputMark := uint32 ( options . AutoRedirectInputMark )
2024-06-07 15:55:21 +08:00
if inputMark == 0 {
inputMark = tun . DefaultAutoRedirectInputMark
}
2024-06-22 14:11:49 +08:00
outputMark := uint32 ( options . AutoRedirectOutputMark )
2024-06-07 15:55:21 +08:00
if outputMark == 0 {
outputMark = tun . DefaultAutoRedirectOutputMark
}
2025-12-26 15:52:28 +08:00
resetMark := uint32 ( options . AutoRedirectResetMark )
if resetMark == 0 {
resetMark = tun . DefaultAutoRedirectResetMark
}
nfQueue := options . AutoRedirectNFQueue
if nfQueue == 0 {
nfQueue = tun . DefaultAutoRedirectNFQueue
}
2026-03-03 20:59:13 +08:00
var includeMACAddress [] net . HardwareAddr
for i , macString := range options . IncludeMACAddress {
mac , macErr := net . ParseMAC ( macString )
if macErr != nil {
return nil , E . Cause ( macErr , "parse include_mac_address[" , i , "]" )
}
includeMACAddress = append ( includeMACAddress , mac )
}
var excludeMACAddress [] net . HardwareAddr
for i , macString := range options . ExcludeMACAddress {
mac , macErr := net . ParseMAC ( macString )
if macErr != nil {
return nil , E . Cause ( macErr , "parse exclude_mac_address[" , i , "]" )
}
excludeMACAddress = append ( excludeMACAddress , mac )
}
2024-11-10 12:11:21 +08:00
networkManager := service . FromContext [ adapter . NetworkManager ]( ctx )
2025-07-18 12:20:26 +08:00
multiPendingPackets := C . IsDarwin && (( options . Stack == "gvisor" && tunMTU < 32768 ) || ( options . Stack != "gvisor" && options . MTU <= 9000 ))
2024-11-02 00:39:02 +08:00
inbound := & Inbound {
2022-08-15 00:25:49 +08:00
tag : tag ,
ctx : ctx ,
router : router ,
2024-11-10 12:11:21 +08:00
networkManager : networkManager ,
2022-08-15 00:25:49 +08:00
logger : logger ,
tunOptions : tun . Options {
2026-01-29 12:07:15 +08:00
Name : options . InterfaceName ,
MTU : tunMTU ,
GSO : enableGSO ,
Inet4Address : inet4Address ,
Inet6Address : inet6Address ,
AutoRoute : options . AutoRoute ,
IPRoute2TableIndex : tableIndex ,
IPRoute2RuleIndex : ruleIndex ,
IPRoute2AutoRedirectFallbackRuleIndex : autoRedirectFallbackRuleIndex ,
AutoRedirectInputMark : inputMark ,
AutoRedirectOutputMark : outputMark ,
AutoRedirectResetMark : resetMark ,
AutoRedirectNFQueue : nfQueue ,
ExcludeMPTCP : options . ExcludeMPTCP ,
Inet4LoopbackAddress : common . Filter ( options . LoopbackAddress , netip . Addr . Is4 ),
Inet6LoopbackAddress : common . Filter ( options . LoopbackAddress , netip . Addr . Is6 ),
StrictRoute : options . StrictRoute ,
IncludeInterface : options . IncludeInterface ,
ExcludeInterface : options . ExcludeInterface ,
Inet4RouteAddress : inet4RouteAddress ,
Inet6RouteAddress : inet6RouteAddress ,
Inet4RouteExcludeAddress : inet4RouteExcludeAddress ,
Inet6RouteExcludeAddress : inet6RouteExcludeAddress ,
IncludeUID : includeUID ,
ExcludeUID : excludeUID ,
IncludeAndroidUser : options . IncludeAndroidUser ,
IncludePackage : options . IncludePackage ,
ExcludePackage : options . ExcludePackage ,
2026-03-03 20:59:13 +08:00
IncludeMACAddress : includeMACAddress ,
ExcludeMACAddress : excludeMACAddress ,
2026-01-29 12:07:15 +08:00
InterfaceMonitor : networkManager . InterfaceMonitor (),
2026-07-09 22:13:03 +08:00
Logger : logger ,
2026-01-29 12:07:15 +08:00
EXP_MultiPendingPackets : multiPendingPackets ,
2022-08-15 00:25:49 +08:00
},
2024-11-23 22:34:02 +08:00
udpTimeout : udpTimeout ,
stack : options . Stack ,
2025-07-02 19:22:23 +08:00
platformInterface : platformInterface ,
2024-11-23 22:34:02 +08:00
platformOptions : common . PtrValueOrDefault ( options . Platform ),
2024-06-07 15:55:21 +08:00
}
2024-12-23 22:24:10 +08:00
for _ , routeAddressSet := range options . RouteAddressSet {
ruleSet , loaded := router . RuleSet ( routeAddressSet )
if ! loaded {
return nil , E . New ( "parse route_address_set: rule-set not found: " , routeAddressSet )
}
inbound . routeRuleSet = append ( inbound . routeRuleSet , ruleSet )
}
for _ , routeExcludeAddressSet := range options . RouteExcludeAddressSet {
ruleSet , loaded := router . RuleSet ( routeExcludeAddressSet )
if ! loaded {
return nil , E . New ( "parse route_exclude_address_set: rule-set not found: " , routeExcludeAddressSet )
}
inbound . routeExcludeRuleSet = append ( inbound . routeExcludeRuleSet , ruleSet )
}
2024-06-07 15:55:21 +08:00
if options . AutoRedirect {
if ! options . AutoRoute {
return nil , E . New ( "`auto_route` is required by `auto_redirect`" )
}
disableNFTables , dErr := strconv . ParseBool ( os . Getenv ( "DISABLE_NFTABLES" ))
inbound . autoRedirect , err = tun . NewAutoRedirect ( tun . AutoRedirectOptions {
TunOptions : & inbound . tunOptions ,
Context : ctx ,
2024-10-21 23:38:34 +08:00
Handler : ( * autoRedirectHandler )( inbound ),
2024-06-07 15:55:21 +08:00
Logger : logger ,
2024-11-10 12:11:21 +08:00
NetworkMonitor : networkManager . NetworkMonitor (),
InterfaceFinder : networkManager . InterfaceFinder (),
2024-06-07 15:55:21 +08:00
TableName : "sing-box" ,
DisableNFTables : dErr == nil && disableNFTables ,
RouteAddressSet : & inbound . routeAddressSet ,
RouteExcludeAddressSet : & inbound . routeExcludeAddressSet ,
})
if err != nil {
return nil , E . Cause ( err , "initialize auto-redirect" )
}
2025-04-02 13:44:39 +08:00
if ! C . IsAndroid {
2024-12-23 22:24:10 +08:00
inbound . tunOptions . AutoRedirectMarkMode = true
err = networkManager . RegisterAutoRedirectOutputMark ( inbound . tunOptions . AutoRedirectOutputMark )
if err != nil {
return nil , err
2024-06-07 15:55:21 +08:00
}
}
}
return inbound , nil
2022-07-09 19:18:37 +08:00
}
2024-11-18 18:55:34 +08:00
func uidToRange ( uidList badoption . Listable [ uint32 ]) [] ranges . Range [ uint32 ] {
2022-08-15 00:25:49 +08:00
return common . Map ( uidList , func ( uid uint32 ) ranges . Range [ uint32 ] {
return ranges . NewSingle ( uid )
})
}
func parseRange ( uidRanges [] ranges . Range [ uint32 ], rangeList [] string ) ([] ranges . Range [ uint32 ], error ) {
for _ , uidRange := range rangeList {
if ! strings . Contains ( uidRange , ":" ) {
return nil , E . New ( "missing ':' in range: " , uidRange )
}
subIndex := strings . Index ( uidRange , ":" )
if subIndex == 0 {
return nil , E . New ( "missing range start: " , uidRange )
} else if subIndex == len ( uidRange ) - 1 {
return nil , E . New ( "missing range end: " , uidRange )
}
var start , end uint64
var err error
2024-06-07 15:55:21 +08:00
start , err = strconv . ParseUint ( uidRange [: subIndex ], 0 , 32 )
2022-08-15 00:25:49 +08:00
if err != nil {
return nil , E . Cause ( err , "parse range start" )
}
2024-06-07 15:55:21 +08:00
end , err = strconv . ParseUint ( uidRange [ subIndex + 1 :], 0 , 32 )
2022-08-15 00:25:49 +08:00
if err != nil {
return nil , E . Cause ( err , "parse range end" )
}
uidRanges = append ( uidRanges , ranges . New ( uint32 ( start ), uint32 ( end )))
}
return uidRanges , nil
}
2024-11-02 00:39:02 +08:00
func ( t * Inbound ) Type () string {
2022-07-09 19:18:37 +08:00
return C . TypeTun
}
2024-11-02 00:39:02 +08:00
func ( t * Inbound ) Tag () string {
2022-07-09 19:18:37 +08:00
return t . tag
}
2024-11-21 18:10:41 +08:00
func ( t * Inbound ) Start ( stage adapter . StartStage ) error {
switch stage {
case adapter . StartStateStart :
if C . IsAndroid && t . platformInterface == nil {
t . tunOptions . BuildAndroidRules ( t . networkManager . PackageManager ())
2024-06-07 15:55:21 +08:00
}
2024-11-21 18:10:41 +08:00
if t . tunOptions . Name == "" {
t . tunOptions . Name = tun . CalculateInterfaceName ( "" )
}
2025-01-27 13:40:26 +08:00
if t . platformInterface == nil {
2024-12-23 22:24:10 +08:00
for _ , routeRuleSet := range t . routeRuleSet {
ipSets := routeRuleSet . ExtractIPSet ()
if len ( ipSets ) == 0 {
t . logger . Warn ( "route_address_set: no destination IP CIDR rules found in rule-set: " , routeRuleSet . Name ())
}
2025-05-20 18:17:20 +08:00
routeRuleSet . IncRef ()
2024-12-23 22:24:10 +08:00
t . routeAddressSet = append ( t . routeAddressSet , ipSets ... )
2025-02-14 13:36:52 +08:00
if t . autoRedirect != nil {
t . routeRuleSetCallback = append ( t . routeRuleSetCallback , routeRuleSet . RegisterCallback ( t . updateRouteAddressSet ))
}
2024-12-23 22:24:10 +08:00
}
for _ , routeExcludeRuleSet := range t . routeExcludeRuleSet {
ipSets := routeExcludeRuleSet . ExtractIPSet ()
if len ( ipSets ) == 0 {
t . logger . Warn ( "route_address_set: no destination IP CIDR rules found in rule-set: " , routeExcludeRuleSet . Name ())
}
2025-05-20 18:17:20 +08:00
routeExcludeRuleSet . IncRef ()
2024-12-23 22:24:10 +08:00
t . routeExcludeAddressSet = append ( t . routeExcludeAddressSet , ipSets ... )
2025-02-14 13:36:52 +08:00
if t . autoRedirect != nil {
t . routeExcludeRuleSetCallback = append ( t . routeExcludeRuleSetCallback , routeExcludeRuleSet . RegisterCallback ( t . updateRouteAddressSet ))
}
2024-12-23 22:24:10 +08:00
}
}
2024-11-21 18:10:41 +08:00
var (
tunInterface tun . Tun
err error
)
monitor := taskmonitor . New ( t . logger , C . StartTimeout )
2024-12-23 22:24:10 +08:00
tunOptions := t . tunOptions
if t . autoRedirect == nil && !( runtime . GOOS == "android" && t . platformInterface != nil ) {
for _ , ipSet := range t . routeAddressSet {
for _ , prefix := range ipSet . Prefixes () {
if prefix . Addr (). Is4 () {
tunOptions . Inet4RouteAddress = append ( tunOptions . Inet4RouteAddress , prefix )
} else {
tunOptions . Inet6RouteAddress = append ( tunOptions . Inet6RouteAddress , prefix )
}
}
}
for _ , ipSet := range t . routeExcludeAddressSet {
for _ , prefix := range ipSet . Prefixes () {
if prefix . Addr (). Is4 () {
tunOptions . Inet4RouteExcludeAddress = append ( tunOptions . Inet4RouteExcludeAddress , prefix )
} else {
tunOptions . Inet6RouteExcludeAddress = append ( tunOptions . Inet6RouteExcludeAddress , prefix )
}
}
}
}
monitor . Start ( "open interface" )
2025-10-07 15:40:11 +08:00
if t . platformInterface != nil && t . platformInterface . UsePlatformInterface () {
tunInterface , err = t . platformInterface . OpenInterface ( & tunOptions , t . platformOptions )
2024-11-21 18:10:41 +08:00
} else {
2025-02-20 16:40:53 +08:00
if HookBeforeCreatePlatformInterface != nil {
HookBeforeCreatePlatformInterface ()
}
2024-12-23 22:24:10 +08:00
tunInterface , err = tun . New ( tunOptions )
2024-06-07 15:55:21 +08:00
}
monitor . Finish ()
2024-12-23 22:24:10 +08:00
t . tunOptions . Name = tunOptions . Name
2024-06-07 15:55:21 +08:00
if err != nil {
2024-11-21 18:10:41 +08:00
return E . Cause ( err , "configure tun interface" )
2024-06-07 15:55:21 +08:00
}
2024-11-21 18:10:41 +08:00
t . logger . Trace ( "creating stack" )
t . tunIf = tunInterface
var (
forwarderBindInterface bool
includeAllNetworks bool
)
if t . platformInterface != nil {
forwarderBindInterface = true
2025-10-07 15:40:11 +08:00
includeAllNetworks = t . platformInterface . NetworkExtensionIncludeAllNetworks ()
2024-06-07 15:55:21 +08:00
}
2024-11-21 18:10:41 +08:00
tunStack , err := tun . NewStack ( t . stack , tun . StackOptions {
Context : t . ctx ,
Tun : tunInterface ,
TunOptions : t . tunOptions ,
UDPTimeout : t . udpTimeout ,
2026-06-01 17:51:02 +08:00
ICMPTimeout : C . ICMPTimeout ,
2024-11-21 18:10:41 +08:00
Handler : t ,
Logger : t . logger ,
ForwarderBindInterface : forwarderBindInterface ,
InterfaceFinder : t . networkManager . InterfaceFinder (),
IncludeAllNetworks : includeAllNetworks ,
})
if err != nil {
return err
}
t . tunStack = tunStack
t . logger . Info ( "started at " , t . tunOptions . Name )
case adapter . StartStatePostStart :
monitor := taskmonitor . New ( t . logger , C . StartTimeout )
monitor . Start ( "starting tun stack" )
err := t . tunStack . Start ()
monitor . Finish ()
if err != nil {
return E . Cause ( err , "starting tun stack" )
}
monitor . Start ( "starting tun interface" )
err = t . tunIf . Start ()
monitor . Finish ()
if err != nil {
return E . Cause ( err , "starting TUN interface" )
}
if t . autoRedirect != nil {
monitor . Start ( "initialize auto-redirect" )
err := t . autoRedirect . Start ()
monitor . Finish ()
if err != nil {
return E . Cause ( err , "auto-redirect" )
}
2024-06-07 15:55:21 +08:00
}
2024-12-23 22:24:10 +08:00
t . routeAddressSet = nil
t . routeExcludeAddressSet = nil
2024-06-07 15:55:21 +08:00
}
return nil
}
2024-11-02 00:39:02 +08:00
func ( t * Inbound ) updateRouteAddressSet ( it adapter . RuleSet ) {
2024-06-07 15:55:21 +08:00
t . routeAddressSet = common . FlatMap ( t . routeRuleSet , adapter . RuleSet . ExtractIPSet )
t . routeExcludeAddressSet = common . FlatMap ( t . routeExcludeRuleSet , adapter . RuleSet . ExtractIPSet )
2025-01-27 13:40:26 +08:00
t . autoRedirect . UpdateRouteAddressSet ()
2024-06-07 15:55:21 +08:00
t . routeAddressSet = nil
t . routeExcludeAddressSet = nil
}
2024-11-02 00:39:02 +08:00
func ( t * Inbound ) Close () error {
2022-07-13 19:01:20 +08:00
return common . Close (
t . tunStack ,
t . tunIf ,
2024-06-07 15:55:21 +08:00
t . autoRedirect ,
2022-07-09 19:18:37 +08:00
)
}
2025-02-17 22:00:57 +08:00
func ( t * Inbound ) PrepareConnection ( network string , source M . Socksaddr , destination M . Socksaddr , routeContext tun . DirectRouteContext , timeout time . Duration ) ( tun . DirectRouteDestination , error ) {
var ipVersion uint8
if ! destination . IsIPv6 () {
ipVersion = 4
} else {
ipVersion = 6
}
routeDestination , err := t . router . PreMatch ( adapter . InboundContext {
2026-02-28 17:55:56 +08:00
Inbound : t . tag ,
InboundType : C . TypeTun ,
IPVersion : ipVersion ,
Network : network ,
Source : source ,
Destination : destination ,
2025-12-27 13:33:58 +08:00
}, routeContext , timeout , false )
2025-02-17 22:00:57 +08:00
if err != nil {
2025-12-26 15:52:28 +08:00
switch {
case rule . IsBypassed ( err ):
err = nil
case rule . IsRejected ( err ):
t . logger . Trace ( "reject " , network , " connection from " , source . AddrString (), " to " , destination . AddrString ())
default :
if network == N . NetworkICMP {
t . logger . Warn ( E . Cause ( err , "link " , network , " connection from " , source . AddrString (), " to " , destination . AddrString ()))
}
2025-02-17 22:00:57 +08:00
}
}
return routeDestination , err
2024-10-21 23:38:34 +08:00
}
2024-11-02 00:39:02 +08:00
func ( t * Inbound ) NewConnectionEx ( ctx context . Context , conn net . Conn , source M . Socksaddr , destination M . Socksaddr , onClose N . CloseHandlerFunc ) {
2022-07-12 15:17:29 +08:00
ctx = log . ContextWithNewID ( ctx )
2022-07-09 19:18:37 +08:00
var metadata adapter . InboundContext
metadata . Inbound = t . tag
2022-07-19 22:16:49 +08:00
metadata . InboundType = C . TypeTun
2024-10-21 23:38:34 +08:00
metadata . Source = source
metadata . Destination = destination
2026-02-28 17:55:56 +08:00
2024-10-21 23:38:34 +08:00
t . logger . InfoContext ( ctx , "inbound connection from " , metadata . Source )
2022-07-12 15:17:29 +08:00
t . logger . InfoContext ( ctx , "inbound connection to " , metadata . Destination )
2024-10-21 23:38:34 +08:00
t . router . RouteConnectionEx ( ctx , conn , metadata , onClose )
2022-07-09 19:18:37 +08:00
}
2024-11-02 00:39:02 +08:00
func ( t * Inbound ) NewPacketConnectionEx ( ctx context . Context , conn N . PacketConn , source M . Socksaddr , destination M . Socksaddr , onClose N . CloseHandlerFunc ) {
2022-07-12 15:17:29 +08:00
ctx = log . ContextWithNewID ( ctx )
2022-07-09 19:18:37 +08:00
var metadata adapter . InboundContext
metadata . Inbound = t . tag
2022-07-19 22:16:49 +08:00
metadata . InboundType = C . TypeTun
2024-10-21 23:38:34 +08:00
metadata . Source = source
metadata . Destination = destination
2026-02-28 17:55:56 +08:00
2022-07-12 15:17:29 +08:00
t . logger . InfoContext ( ctx , "inbound packet connection from " , metadata . Source )
t . logger . InfoContext ( ctx , "inbound packet connection to " , metadata . Destination )
2024-10-21 23:38:34 +08:00
t . router . RoutePacketConnectionEx ( ctx , conn , metadata , onClose )
2022-07-09 19:18:37 +08:00
}
2024-11-02 00:39:02 +08:00
type autoRedirectHandler Inbound
2024-10-21 23:38:34 +08:00
2025-12-26 15:52:28 +08:00
func ( t * autoRedirectHandler ) PrepareConnection ( network string , source M . Socksaddr , destination M . Socksaddr , routeContext tun . DirectRouteContext , timeout time . Duration ) ( tun . DirectRouteDestination , error ) {
var ipVersion uint8
if ! destination . IsIPv6 () {
ipVersion = 4
} else {
ipVersion = 6
}
routeDestination , err := t . router . PreMatch ( adapter . InboundContext {
2026-02-28 17:55:56 +08:00
Inbound : t . tag ,
InboundType : C . TypeTun ,
IPVersion : ipVersion ,
Network : network ,
Source : source ,
Destination : destination ,
2025-12-27 13:33:58 +08:00
}, routeContext , timeout , true )
2025-12-26 15:52:28 +08:00
if err != nil {
switch {
case rule . IsBypassed ( err ):
t . logger . Trace ( "bypass " , network , " connection from " , source . AddrString (), " to " , destination . AddrString ())
case rule . IsRejected ( err ):
t . logger . Trace ( "reject " , network , " connection from " , source . AddrString (), " to " , destination . AddrString ())
default :
if network == N . NetworkICMP {
t . logger . Warn ( E . Cause ( err , "link " , network , " connection from " , source . AddrString (), " to " , destination . AddrString ()))
}
}
}
return routeDestination , err
}
2024-10-21 23:38:34 +08:00
func ( t * autoRedirectHandler ) NewConnectionEx ( ctx context . Context , conn net . Conn , source M . Socksaddr , destination M . Socksaddr , onClose N . CloseHandlerFunc ) {
ctx = log . ContextWithNewID ( ctx )
var metadata adapter . InboundContext
metadata . Inbound = t . tag
metadata . InboundType = C . TypeTun
metadata . Source = source
metadata . Destination = destination
2026-02-28 17:55:56 +08:00
2024-10-21 23:38:34 +08:00
t . logger . InfoContext ( ctx , "inbound redirect connection from " , metadata . Source )
t . logger . InfoContext ( ctx , "inbound connection to " , metadata . Destination )
t . router . RouteConnectionEx ( ctx , conn , metadata , onClose )
2022-07-09 19:18:37 +08:00
}
2025-12-26 15:52:28 +08:00
func ( t * autoRedirectHandler ) NewPacketConnectionEx ( ctx context . Context , conn N . PacketConn , source M . Socksaddr , destination M . Socksaddr , onClose N . CloseHandlerFunc ) {
panic ( "unexcepted" )
}