github.com/sagernet/sing-box@v1.9.0-rc.20/inbound/default.go (about) 1 package inbound 2 3 import ( 4 "context" 5 "net" 6 7 "github.com/sagernet/sing-box/adapter" 8 "github.com/sagernet/sing-box/common/settings" 9 C "github.com/sagernet/sing-box/constant" 10 "github.com/sagernet/sing-box/log" 11 "github.com/sagernet/sing-box/option" 12 "github.com/sagernet/sing/common" 13 "github.com/sagernet/sing/common/atomic" 14 E "github.com/sagernet/sing/common/exceptions" 15 M "github.com/sagernet/sing/common/metadata" 16 N "github.com/sagernet/sing/common/network" 17 ) 18 19 var _ adapter.Inbound = (*myInboundAdapter)(nil) 20 21 type myInboundAdapter struct { 22 protocol string 23 network []string 24 ctx context.Context 25 router adapter.ConnectionRouter 26 logger log.ContextLogger 27 tag string 28 listenOptions option.ListenOptions 29 connHandler adapter.ConnectionHandler 30 packetHandler adapter.PacketHandler 31 oobPacketHandler adapter.OOBPacketHandler 32 packetUpstream any 33 34 // http mixed 35 36 setSystemProxy bool 37 systemProxy settings.SystemProxy 38 39 // internal 40 41 tcpListener net.Listener 42 udpConn *net.UDPConn 43 udpAddr M.Socksaddr 44 packetOutboundClosed chan struct{} 45 packetOutbound chan *myInboundPacket 46 47 inShutdown atomic.Bool 48 } 49 50 func (a *myInboundAdapter) Type() string { 51 return a.protocol 52 } 53 54 func (a *myInboundAdapter) Tag() string { 55 return a.tag 56 } 57 58 func (a *myInboundAdapter) Network() []string { 59 return a.network 60 } 61 62 func (a *myInboundAdapter) Start() error { 63 var err error 64 if common.Contains(a.network, N.NetworkTCP) { 65 _, err = a.ListenTCP() 66 if err != nil { 67 return err 68 } 69 go a.loopTCPIn() 70 } 71 if common.Contains(a.network, N.NetworkUDP) { 72 _, err = a.ListenUDP() 73 if err != nil { 74 return err 75 } 76 a.packetOutboundClosed = make(chan struct{}) 77 a.packetOutbound = make(chan *myInboundPacket) 78 if a.oobPacketHandler != nil { 79 if _, threadUnsafeHandler := common.Cast[N.ThreadUnsafeWriter](a.packetUpstream); !threadUnsafeHandler { 80 go a.loopUDPOOBIn() 81 } else { 82 go a.loopUDPOOBInThreadSafe() 83 } 84 } else { 85 if _, threadUnsafeHandler := common.Cast[N.ThreadUnsafeWriter](a.packetUpstream); !threadUnsafeHandler { 86 go a.loopUDPIn() 87 } else { 88 go a.loopUDPInThreadSafe() 89 } 90 go a.loopUDPOut() 91 } 92 } 93 if a.setSystemProxy { 94 listenPort := M.SocksaddrFromNet(a.tcpListener.Addr()).Port 95 var listenAddrString string 96 listenAddr := a.listenOptions.Listen.Build() 97 if listenAddr.IsUnspecified() { 98 listenAddrString = "127.0.0.1" 99 } else { 100 listenAddrString = listenAddr.String() 101 } 102 var systemProxy settings.SystemProxy 103 systemProxy, err = settings.NewSystemProxy(a.ctx, M.ParseSocksaddrHostPort(listenAddrString, listenPort), a.protocol == C.TypeMixed) 104 if err != nil { 105 return E.Cause(err, "initialize system proxy") 106 } 107 err = systemProxy.Enable() 108 if err != nil { 109 return E.Cause(err, "set system proxy") 110 } 111 a.systemProxy = systemProxy 112 } 113 return nil 114 } 115 116 func (a *myInboundAdapter) Close() error { 117 a.inShutdown.Store(true) 118 var err error 119 if a.systemProxy != nil && a.systemProxy.IsEnabled() { 120 err = a.systemProxy.Disable() 121 } 122 return E.Errors(err, common.Close( 123 a.tcpListener, 124 common.PtrOrNil(a.udpConn), 125 )) 126 } 127 128 func (a *myInboundAdapter) upstreamHandler(metadata adapter.InboundContext) adapter.UpstreamHandlerAdapter { 129 return adapter.NewUpstreamHandler(metadata, a.newConnection, a.streamPacketConnection, a) 130 } 131 132 func (a *myInboundAdapter) upstreamContextHandler() adapter.UpstreamHandlerAdapter { 133 return adapter.NewUpstreamContextHandler(a.newConnection, a.newPacketConnection, a) 134 } 135 136 func (a *myInboundAdapter) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { 137 a.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) 138 return a.router.RouteConnection(ctx, conn, metadata) 139 } 140 141 func (a *myInboundAdapter) streamPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 142 a.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) 143 return a.router.RoutePacketConnection(ctx, conn, metadata) 144 } 145 146 func (a *myInboundAdapter) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 147 ctx = log.ContextWithNewID(ctx) 148 a.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source) 149 a.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) 150 return a.router.RoutePacketConnection(ctx, conn, metadata) 151 } 152 153 func (a *myInboundAdapter) createMetadata(conn net.Conn, metadata adapter.InboundContext) adapter.InboundContext { 154 metadata.Inbound = a.tag 155 metadata.InboundType = a.protocol 156 metadata.InboundDetour = a.listenOptions.Detour 157 metadata.InboundOptions = a.listenOptions.InboundOptions 158 if !metadata.Source.IsValid() { 159 metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr()).Unwrap() 160 } 161 if !metadata.Destination.IsValid() { 162 metadata.Destination = M.SocksaddrFromNet(conn.LocalAddr()).Unwrap() 163 } 164 if tcpConn, isTCP := common.Cast[*net.TCPConn](conn); isTCP { 165 metadata.OriginDestination = M.SocksaddrFromNet(tcpConn.LocalAddr()).Unwrap() 166 } 167 return metadata 168 } 169 170 func (a *myInboundAdapter) createPacketMetadata(conn N.PacketConn, metadata adapter.InboundContext) adapter.InboundContext { 171 metadata.Inbound = a.tag 172 metadata.InboundType = a.protocol 173 metadata.InboundDetour = a.listenOptions.Detour 174 metadata.InboundOptions = a.listenOptions.InboundOptions 175 if !metadata.Destination.IsValid() { 176 metadata.Destination = M.SocksaddrFromNet(conn.LocalAddr()).Unwrap() 177 } 178 return metadata 179 } 180 181 func (a *myInboundAdapter) newError(err error) { 182 a.logger.Error(err) 183 } 184 185 func (a *myInboundAdapter) NewError(ctx context.Context, err error) { 186 NewError(a.logger, ctx, err) 187 } 188 189 func NewError(logger log.ContextLogger, ctx context.Context, err error) { 190 common.Close(err) 191 if E.IsClosedOrCanceled(err) { 192 logger.DebugContext(ctx, "connection closed: ", err) 193 return 194 } 195 logger.ErrorContext(ctx, err) 196 }