mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-12 18:17:18 +10:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b8ab3e61e | ||
|
|
47f18e823a | ||
|
|
2d1b824b62 | ||
|
|
d511698f3f | ||
|
|
cb435ea232 | ||
|
|
43a9016c83 | ||
|
|
255068fd40 | ||
|
|
098a00b025 | ||
|
|
dba0b5276b | ||
|
|
78ae935468 | ||
|
|
3ea5f76470 | ||
|
|
b4d294c05e | ||
|
|
83cf5f5c6a | ||
|
|
e7b3a8eebe | ||
|
|
ee3a42a67e | ||
|
|
50227c0f5f | ||
|
|
bc5eb1e1a5 | ||
|
|
995267a042 | ||
|
|
41226a6075 | ||
|
|
81d32181ce | ||
|
|
c5ecca3938 | ||
|
|
900888731c | ||
|
|
13e648e4b1 |
Submodule clients/android updated: 9dd336679d...eb2e13a6f9
@@ -100,10 +100,6 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
|
||||
} else if networkManager.AutoDetectInterface() {
|
||||
if platformInterface != nil {
|
||||
networkStrategy = (*C.NetworkStrategy)(options.NetworkStrategy)
|
||||
if networkStrategy == nil {
|
||||
networkStrategy = common.Ptr(C.NetworkStrategyDefault)
|
||||
defaultNetworkStrategy = true
|
||||
}
|
||||
networkType = common.Map(options.NetworkType, option.InterfaceType.Build)
|
||||
fallbackNetworkType = common.Map(options.FallbackNetworkType, option.InterfaceType.Build)
|
||||
if networkStrategy == nil && len(networkType) == 0 && len(fallbackNetworkType) == 0 {
|
||||
@@ -115,6 +111,10 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
|
||||
if networkFallbackDelay == 0 && defaultOptions.FallbackDelay != 0 {
|
||||
networkFallbackDelay = defaultOptions.FallbackDelay
|
||||
}
|
||||
if networkStrategy == nil {
|
||||
networkStrategy = common.Ptr(C.NetworkStrategyDefault)
|
||||
defaultNetworkStrategy = true
|
||||
}
|
||||
bindFunc := networkManager.ProtectFunc()
|
||||
dialer.Control = control.Append(dialer.Control, bindFunc)
|
||||
listener.Control = control.Append(listener.Control, bindFunc)
|
||||
|
||||
@@ -10,9 +10,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
@@ -26,7 +24,9 @@ type slowOpenConn struct {
|
||||
destination M.Socksaddr
|
||||
conn net.Conn
|
||||
create chan struct{}
|
||||
done chan struct{}
|
||||
access sync.Mutex
|
||||
closeOnce sync.Once
|
||||
err error
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ func DialSlowContext(dialer *tcpDialer, ctx context.Context, network string, des
|
||||
network: network,
|
||||
destination: destination,
|
||||
create: make(chan struct{}),
|
||||
done: make(chan struct{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -55,8 +56,8 @@ func (c *slowOpenConn) Read(b []byte) (n int, err error) {
|
||||
if c.err != nil {
|
||||
return 0, c.err
|
||||
}
|
||||
case <-c.ctx.Done():
|
||||
return 0, c.ctx.Err()
|
||||
case <-c.done:
|
||||
return 0, os.ErrClosed
|
||||
}
|
||||
}
|
||||
return c.conn.Read(b)
|
||||
@@ -74,12 +75,15 @@ func (c *slowOpenConn) Write(b []byte) (n int, err error) {
|
||||
return 0, c.err
|
||||
}
|
||||
return c.conn.Write(b)
|
||||
case <-c.done:
|
||||
return 0, os.ErrClosed
|
||||
default:
|
||||
}
|
||||
c.conn, err = c.dialer.DialContext(c.ctx, c.network, c.destination.String(), b)
|
||||
conn, err := c.dialer.DialContext(c.ctx, c.network, c.destination.String(), b)
|
||||
if err != nil {
|
||||
c.conn = nil
|
||||
c.err = E.Cause(err, "dial tcp fast open")
|
||||
c.err = err
|
||||
} else {
|
||||
c.conn = conn
|
||||
}
|
||||
n = len(b)
|
||||
close(c.create)
|
||||
@@ -87,7 +91,13 @@ func (c *slowOpenConn) Write(b []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
func (c *slowOpenConn) Close() error {
|
||||
return common.Close(c.conn)
|
||||
c.closeOnce.Do(func() {
|
||||
close(c.done)
|
||||
if c.conn != nil {
|
||||
c.conn.Close()
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *slowOpenConn) LocalAddr() net.Addr {
|
||||
@@ -152,8 +162,8 @@ func (c *slowOpenConn) WriteTo(w io.Writer) (n int64, err error) {
|
||||
if c.err != nil {
|
||||
return 0, c.err
|
||||
}
|
||||
case <-c.ctx.Done():
|
||||
return 0, c.ctx.Err()
|
||||
case <-c.done:
|
||||
return 0, c.err
|
||||
}
|
||||
}
|
||||
return bufio.Copy(w, c.conn)
|
||||
|
||||
@@ -76,6 +76,8 @@ func findProcessName(network string, ip netip.Addr, port int) (string, error) {
|
||||
// rup8(sizeof(xtcpcb_n))
|
||||
itemSize += 208
|
||||
}
|
||||
|
||||
var fallbackUDPProcess string
|
||||
// skip the first xinpgen(24 bytes) block
|
||||
for i := 24; i+itemSize <= len(buf); i += itemSize {
|
||||
// offset of xinpcb_n and xsocket_n
|
||||
@@ -90,10 +92,12 @@ func findProcessName(network string, ip netip.Addr, port int) (string, error) {
|
||||
flag := buf[inp+44]
|
||||
|
||||
var srcIP netip.Addr
|
||||
srcIsIPv4 := false
|
||||
switch {
|
||||
case flag&0x1 > 0 && isIPv4:
|
||||
// ipv4
|
||||
srcIP = netip.AddrFrom4(*(*[4]byte)(buf[inp+76 : inp+80]))
|
||||
srcIsIPv4 = true
|
||||
case flag&0x2 > 0 && !isIPv4:
|
||||
// ipv6
|
||||
srcIP = netip.AddrFrom16(*(*[16]byte)(buf[inp+64 : inp+80]))
|
||||
@@ -101,13 +105,21 @@ func findProcessName(network string, ip netip.Addr, port int) (string, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
if ip != srcIP {
|
||||
continue
|
||||
if ip == srcIP {
|
||||
// xsocket_n.so_last_pid
|
||||
pid := readNativeUint32(buf[so+68 : so+72])
|
||||
return getExecPathFromPID(pid)
|
||||
}
|
||||
|
||||
// xsocket_n.so_last_pid
|
||||
pid := readNativeUint32(buf[so+68 : so+72])
|
||||
return getExecPathFromPID(pid)
|
||||
// udp packet connection may be not equal with srcIP
|
||||
if network == N.NetworkUDP && srcIP.IsUnspecified() && isIPv4 == srcIsIPv4 {
|
||||
pid := readNativeUint32(buf[so+68 : so+72])
|
||||
fallbackUDPProcess, _ = getExecPathFromPID(pid)
|
||||
}
|
||||
}
|
||||
|
||||
if network == N.NetworkUDP && len(fallbackUDPProcess) > 0 {
|
||||
return fallbackUDPProcess, nil
|
||||
}
|
||||
|
||||
return "", ErrNotFound
|
||||
|
||||
@@ -2,6 +2,27 @@
|
||||
icon: material/alert-decagram
|
||||
---
|
||||
|
||||
### 1.11.14
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||
violated the rules (TestFlight users are not affected)._
|
||||
|
||||
### 1.11.13
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||
violated the rules (TestFlight users are not affected)._
|
||||
|
||||
### 1.11.11
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||
violated the rules (TestFlight users are not affected)._
|
||||
|
||||
### 1.11.10
|
||||
|
||||
* Undeprecate the `block` outbound **1**
|
||||
|
||||
@@ -398,11 +398,11 @@ UDP NAT 过期时间。
|
||||
|
||||
TCP/IP 栈。
|
||||
|
||||
| 栈 | 描述 |
|
||||
|--------|------------------------------------------------------------------|
|
||||
| system | 基于系统网络栈执行 L3 到 L4 转换 |
|
||||
| gVisor | 基于 [gVisor](https://github.com/google/gvisor) 虚拟网络栈执行 L3 到 L4 转换 |
|
||||
| mixed | 混合 `system` TCP 栈与 `gvisor` UDP 栈 |
|
||||
| 栈 | 描述 |
|
||||
|----------|-------------------------------------------------------------------------------------------------------|
|
||||
| `system` | 基于系统网络栈执行 L3 到 L4 转换 |
|
||||
| `gvisor` | 基于 [gVisor](https://github.com/google/gvisor) 虚拟网络栈执行 L3 到 L4 转换 |
|
||||
| `mixed` | 混合 `system` TCP 栈与 `gvisor` UDP 栈 |
|
||||
|
||||
默认使用 `mixed` 栈如果 gVisor 构建标记已启用,否则默认使用 `system` 栈。
|
||||
|
||||
|
||||
14
go.mod
14
go.mod
@@ -26,15 +26,15 @@ require (
|
||||
github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff
|
||||
github.com/sagernet/quic-go v0.49.0-beta.1
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||
github.com/sagernet/sing v0.6.9
|
||||
github.com/sagernet/sing-dns v0.4.2
|
||||
github.com/sagernet/sing v0.6.10
|
||||
github.com/sagernet/sing-dns v0.4.5
|
||||
github.com/sagernet/sing-mux v0.3.2
|
||||
github.com/sagernet/sing-quic v0.4.1-0.20250423030647-0eb05f373a76
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||
github.com/sagernet/sing-quic v0.4.3
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
||||
github.com/sagernet/sing-shadowtls v0.2.0
|
||||
github.com/sagernet/sing-tun v0.6.5
|
||||
github.com/sagernet/sing-vmess v0.2.1
|
||||
github.com/sagernet/sing-tun v0.6.8
|
||||
github.com/sagernet/sing-vmess v0.2.3
|
||||
github.com/sagernet/smux v1.5.34-mod.2
|
||||
github.com/sagernet/utls v1.6.7
|
||||
github.com/sagernet/wireguard-go v0.0.1-beta.7
|
||||
|
||||
27
go.sum
27
go.sum
@@ -118,24 +118,25 @@ github.com/sagernet/quic-go v0.49.0-beta.1 h1:3LdoCzVVfYRibZns1tYWSIoB65fpTmrwy+
|
||||
github.com/sagernet/quic-go v0.49.0-beta.1/go.mod h1:uesWD1Ihrldq1M3XtjuEvIUqi8WHNsRs71b3Lt1+p/U=
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||
github.com/sagernet/sing v0.6.9 h1:y/XJH17oyBd6hxgQtKnIdLXu7TsOHxO5i1JeVfVmjXw=
|
||||
github.com/sagernet/sing v0.6.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-dns v0.4.2 h1:cWe2XPUBFLep2j9kJV4Epg3bctGhMvrrl/sWi9Wszfg=
|
||||
github.com/sagernet/sing-dns v0.4.2/go.mod h1:dweQs54ng2YGzoJfz+F9dGuDNdP5pJ3PLeggnK5VWc8=
|
||||
github.com/sagernet/sing v0.6.10 h1:Jey1tePgH9bjFuK1fQI3D9T+bPOQ4SdHMjuS4sYjDv4=
|
||||
github.com/sagernet/sing v0.6.10/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-dns v0.4.5 h1:D9REN14qx2FTrZRBrtFLL99f2CuFzQ9S7mIf8uV5hZI=
|
||||
github.com/sagernet/sing-dns v0.4.5/go.mod h1:dweQs54ng2YGzoJfz+F9dGuDNdP5pJ3PLeggnK5VWc8=
|
||||
github.com/sagernet/sing-mux v0.3.2 h1:meZVFiiStvHThb/trcpAkCrmtJOuItG5Dzl1RRP5/NE=
|
||||
github.com/sagernet/sing-mux v0.3.2/go.mod h1:pht8iFY4c9Xltj7rhVd208npkNaeCxzyXCgulDPLUDA=
|
||||
github.com/sagernet/sing-quic v0.4.1-0.20250423030647-0eb05f373a76 h1:iwpCX6H3nZEOGUGwx0q5azcgYOA9f6v9YssihXoRKHk=
|
||||
github.com/sagernet/sing-quic v0.4.1-0.20250423030647-0eb05f373a76/go.mod h1:tqPa0/Wqa19MkkSlKVZZX5sHxtiDR9BROcn4ufcbVdY=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||
github.com/sagernet/sing-quic v0.4.3 h1:OZ/kGvSzjtYg+t0DY3F606hlT5LeiQQXDxfBopcRryQ=
|
||||
github.com/sagernet/sing-quic v0.4.3/go.mod h1:tqPa0/Wqa19MkkSlKVZZX5sHxtiDR9BROcn4ufcbVdY=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnqqs2gQ2/Qioo=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||
github.com/sagernet/sing-shadowtls v0.2.0 h1:cLKe4OAOFwuhmAIuPLj//CIL7Q9js+pIDardhJ+/osk=
|
||||
github.com/sagernet/sing-shadowtls v0.2.0/go.mod h1:agU+Fw5X+xnWVyRHyFthoZCX3MfWKCFPm4JUf+1oaxo=
|
||||
github.com/sagernet/sing-tun v0.6.5 h1:nGfD6GNq/r0tEjdZHOV3BS6fydSmd4kBAokU5rffssg=
|
||||
github.com/sagernet/sing-tun v0.6.5/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||
github.com/sagernet/sing-vmess v0.2.1 h1:6izHC2+B68aQCxTagki6eZZc+g5eh4dYwxOV5a2Lhug=
|
||||
github.com/sagernet/sing-vmess v0.2.1/go.mod h1:jDAZ0A0St1zVRkyvhAPRySOFfhC+4SQtO5VYyeFotgA=
|
||||
github.com/sagernet/sing-tun v0.6.8 h1:tr+LKHe09C2I9GfNuB2vnzaZm+ekoNlAhLLrdiLjtAA=
|
||||
github.com/sagernet/sing-tun v0.6.8/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||
github.com/sagernet/sing-vmess v0.2.3 h1:z6Ym8dnZG7k1fP3+54vz8G0tvRVJeOoTFFeUPwXTD44=
|
||||
github.com/sagernet/sing-vmess v0.2.3/go.mod h1:jDAZ0A0St1zVRkyvhAPRySOFfhC+4SQtO5VYyeFotgA=
|
||||
github.com/sagernet/smux v1.5.34-mod.2 h1:gkmBjIjlJ2zQKpLigOkFur5kBKdV6bNRoFu2WkltRQ4=
|
||||
github.com/sagernet/smux v1.5.34-mod.2/go.mod h1:0KW0+R+ycvA2INW4gbsd7BNyg+HEfLIAxa5N02/28Zc=
|
||||
github.com/sagernet/utls v1.6.7 h1:Ep3+aJ8FUGGta+II2IEVNUc3EDhaRCZINWkj/LloIA8=
|
||||
|
||||
@@ -214,7 +214,6 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||
if !loaded {
|
||||
return nil, E.New("parse route_address_set: rule-set not found: ", routeAddressSet)
|
||||
}
|
||||
ruleSet.IncRef()
|
||||
inbound.routeRuleSet = append(inbound.routeRuleSet, ruleSet)
|
||||
}
|
||||
for _, routeExcludeAddressSet := range options.RouteExcludeAddressSet {
|
||||
@@ -222,7 +221,6 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||
if !loaded {
|
||||
return nil, E.New("parse route_exclude_address_set: rule-set not found: ", routeExcludeAddressSet)
|
||||
}
|
||||
ruleSet.IncRef()
|
||||
inbound.routeExcludeRuleSet = append(inbound.routeExcludeRuleSet, ruleSet)
|
||||
}
|
||||
if options.AutoRedirect {
|
||||
@@ -312,7 +310,7 @@ func (t *Inbound) Start(stage adapter.StartStage) error {
|
||||
if len(ipSets) == 0 {
|
||||
t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeRuleSet.Name())
|
||||
}
|
||||
routeRuleSet.DecRef()
|
||||
routeRuleSet.IncRef()
|
||||
t.routeAddressSet = append(t.routeAddressSet, ipSets...)
|
||||
if t.autoRedirect != nil {
|
||||
t.routeRuleSetCallback = append(t.routeRuleSetCallback, routeRuleSet.RegisterCallback(t.updateRouteAddressSet))
|
||||
@@ -324,7 +322,7 @@ func (t *Inbound) Start(stage adapter.StartStage) error {
|
||||
if len(ipSets) == 0 {
|
||||
t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeExcludeRuleSet.Name())
|
||||
}
|
||||
routeExcludeRuleSet.DecRef()
|
||||
routeExcludeRuleSet.IncRef()
|
||||
t.routeExcludeAddressSet = append(t.routeExcludeAddressSet, ipSets...)
|
||||
if t.autoRedirect != nil {
|
||||
t.routeExcludeRuleSetCallback = append(t.routeExcludeRuleSetCallback, routeExcludeRuleSet.RegisterCallback(t.updateRouteAddressSet))
|
||||
|
||||
12
route/dns.go
12
route/dns.go
@@ -31,7 +31,7 @@ func (r *Router) hijackDNSStream(ctx context.Context, conn net.Conn, metadata ad
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Router) hijackDNSPacket(ctx context.Context, conn N.PacketConn, packetBuffers []*N.PacketBuffer, metadata adapter.InboundContext) {
|
||||
func (r *Router) hijackDNSPacket(ctx context.Context, conn N.PacketConn, packetBuffers []*N.PacketBuffer, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
|
||||
if natConn, isNatConn := conn.(udpnat.Conn); isNatConn {
|
||||
metadata.Destination = M.Socksaddr{}
|
||||
for _, packet := range packetBuffers {
|
||||
@@ -45,10 +45,12 @@ func (r *Router) hijackDNSPacket(ctx context.Context, conn N.PacketConn, packetB
|
||||
conn: conn,
|
||||
ctx: ctx,
|
||||
metadata: metadata,
|
||||
onClose: onClose,
|
||||
})
|
||||
return
|
||||
}
|
||||
err := dnsOutbound.NewDNSPacketConnection(ctx, r, conn, packetBuffers, metadata)
|
||||
N.CloseOnHandshakeFailure(conn, onClose, err)
|
||||
if err != nil && !E.IsClosedOrCanceled(err) {
|
||||
r.dnsLogger.ErrorContext(ctx, E.Cause(err, "process packet connection"))
|
||||
}
|
||||
@@ -85,8 +87,16 @@ type dnsHijacker struct {
|
||||
conn N.PacketConn
|
||||
ctx context.Context
|
||||
metadata adapter.InboundContext
|
||||
onClose N.CloseHandlerFunc
|
||||
}
|
||||
|
||||
func (h *dnsHijacker) NewPacketEx(buffer *buf.Buffer, destination M.Socksaddr) {
|
||||
go ExchangeDNSPacket(h.ctx, h.router, h.conn, buffer, h.metadata, destination)
|
||||
}
|
||||
|
||||
func (h *dnsHijacker) Close() error {
|
||||
if h.onClose != nil {
|
||||
h.onClose(nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||
for _, buffer := range buffers {
|
||||
conn = bufio.NewCachedConn(conn, buffer)
|
||||
}
|
||||
r.hijackDNSStream(ctx, conn, metadata)
|
||||
N.CloseOnHandshakeFailure(conn, onClose, r.hijackDNSStream(ctx, conn, metadata))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -176,8 +176,6 @@ func (r *Router) RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn,
|
||||
} else {
|
||||
r.logger.ErrorContext(ctx, err)
|
||||
}
|
||||
} else if onClose != nil {
|
||||
onClose(nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +233,7 @@ func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||
N.CloseOnHandshakeFailure(conn, onClose, action.Error(ctx))
|
||||
return nil
|
||||
case *rule.RuleActionHijackDNS:
|
||||
r.hijackDNSPacket(ctx, conn, packetBuffers, metadata)
|
||||
r.hijackDNSPacket(ctx, conn, packetBuffers, metadata, onClose)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -498,7 +496,9 @@ func (r *Router) actionSniff(
|
||||
return
|
||||
}
|
||||
if inputConn != nil {
|
||||
sniffBuffer := buf.NewPacket()
|
||||
if len(action.StreamSniffers) == 0 && len(action.PacketSniffers) > 0 {
|
||||
return
|
||||
}
|
||||
var streamSniffers []sniff.StreamSniffer
|
||||
if len(action.StreamSniffers) > 0 {
|
||||
streamSniffers = action.StreamSniffers
|
||||
@@ -512,6 +512,7 @@ func (r *Router) actionSniff(
|
||||
sniff.RDP,
|
||||
}
|
||||
}
|
||||
sniffBuffer := buf.NewPacket()
|
||||
err := sniff.PeekStream(
|
||||
ctx,
|
||||
metadata,
|
||||
@@ -543,10 +544,25 @@ func (r *Router) actionSniff(
|
||||
sniffBuffer.Release()
|
||||
}
|
||||
} else if inputPacketConn != nil {
|
||||
if metadata.PacketSniffError != nil && !errors.Is(metadata.PacketSniffError, sniff.ErrNeedMoreData) {
|
||||
if len(action.PacketSniffers) == 0 && len(action.StreamSniffers) > 0 {
|
||||
return
|
||||
} else if metadata.PacketSniffError != nil && !errors.Is(metadata.PacketSniffError, sniff.ErrNeedMoreData) {
|
||||
r.logger.DebugContext(ctx, "packet sniff skipped due to previous error: ", metadata.PacketSniffError)
|
||||
return
|
||||
}
|
||||
var packetSniffers []sniff.PacketSniffer
|
||||
if len(action.PacketSniffers) > 0 {
|
||||
packetSniffers = action.PacketSniffers
|
||||
} else {
|
||||
packetSniffers = []sniff.PacketSniffer{
|
||||
sniff.DomainNameQuery,
|
||||
sniff.QUICClientHello,
|
||||
sniff.STUNMessage,
|
||||
sniff.UTP,
|
||||
sniff.UDPTracker,
|
||||
sniff.DTLSRecord,
|
||||
}
|
||||
}
|
||||
for {
|
||||
var (
|
||||
sniffBuffer = buf.NewPacket()
|
||||
@@ -586,19 +602,6 @@ func (r *Router) actionSniff(
|
||||
sniff.QUICClientHello,
|
||||
)
|
||||
} else {
|
||||
var packetSniffers []sniff.PacketSniffer
|
||||
if len(action.PacketSniffers) > 0 {
|
||||
packetSniffers = action.PacketSniffers
|
||||
} else {
|
||||
packetSniffers = []sniff.PacketSniffer{
|
||||
sniff.DomainNameQuery,
|
||||
sniff.QUICClientHello,
|
||||
sniff.STUNMessage,
|
||||
sniff.UTP,
|
||||
sniff.UDPTracker,
|
||||
sniff.DTLSRecord,
|
||||
}
|
||||
}
|
||||
err = sniff.PeekPacket(
|
||||
ctx, metadata,
|
||||
sniffBuffer.Bytes(),
|
||||
|
||||
@@ -161,7 +161,14 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er
|
||||
case *R.RuleActionReject:
|
||||
switch action.Method {
|
||||
case C.RuleActionRejectMethodDefault:
|
||||
return dns.FixedResponse(message.Id, message.Question[0], nil, 0), nil
|
||||
return &mDNS.Msg{
|
||||
MsgHdr: mDNS.MsgHdr{
|
||||
Id: message.Id,
|
||||
Rcode: mDNS.RcodeRefused,
|
||||
Response: true,
|
||||
},
|
||||
Question: []mDNS.Question{message.Question[0]},
|
||||
}, nil
|
||||
case C.RuleActionRejectMethodDrop:
|
||||
return nil, tun.ErrDrop
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ func NewServer(ctx context.Context, logger logger.ContextLogger, options option.
|
||||
server := &Server{
|
||||
ctx: ctx,
|
||||
tlsConfig: tlsConfig,
|
||||
logger: logger,
|
||||
handler: handler,
|
||||
h2Server: &http2.Server{
|
||||
IdleTimeout: time.Duration(options.IdleTimeout),
|
||||
|
||||
@@ -3,6 +3,7 @@ package v2raywebsocket
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
@@ -67,9 +68,10 @@ func (c *WebsocketConn) Read(b []byte) (n int, err error) {
|
||||
return
|
||||
}
|
||||
if !E.IsMulti(err, io.EOF, wsutil.ErrNoFrameAdvance) {
|
||||
err = wrapWsError(err)
|
||||
return
|
||||
}
|
||||
header, err = c.reader.NextFrame()
|
||||
header, err = wrapWsError0(c.reader.NextFrame())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -78,14 +80,14 @@ func (c *WebsocketConn) Read(b []byte) (n int, err error) {
|
||||
err = wsutil.ErrFrameTooLarge
|
||||
return
|
||||
}
|
||||
err = c.controlHandler(header, c.reader)
|
||||
err = wrapWsError(c.controlHandler(header, c.reader))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
if header.OpCode&ws.OpBinary == 0 {
|
||||
err = c.reader.Discard()
|
||||
err = wrapWsError(c.reader.Discard())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -95,7 +97,7 @@ func (c *WebsocketConn) Read(b []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
func (c *WebsocketConn) Write(p []byte) (n int, err error) {
|
||||
err = wsutil.WriteMessage(c.Conn, c.state, ws.OpBinary, p)
|
||||
err = wrapWsError(wsutil.WriteMessage(c.Conn, c.state, ws.OpBinary, p))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -146,7 +148,7 @@ func (c *EarlyWebsocketConn) Read(b []byte) (n int, err error) {
|
||||
return 0, c.err
|
||||
}
|
||||
}
|
||||
return c.conn.Read(b)
|
||||
return wrapWsError0(c.conn.Read(b))
|
||||
}
|
||||
|
||||
func (c *EarlyWebsocketConn) writeRequest(content []byte) error {
|
||||
@@ -191,7 +193,7 @@ func (c *EarlyWebsocketConn) writeRequest(content []byte) error {
|
||||
|
||||
func (c *EarlyWebsocketConn) Write(b []byte) (n int, err error) {
|
||||
if c.conn != nil {
|
||||
return c.conn.Write(b)
|
||||
return wrapWsError0(c.conn.Write(b))
|
||||
}
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
@@ -199,7 +201,7 @@ func (c *EarlyWebsocketConn) Write(b []byte) (n int, err error) {
|
||||
return 0, c.err
|
||||
}
|
||||
if c.conn != nil {
|
||||
return c.conn.Write(b)
|
||||
return wrapWsError0(c.conn.Write(b))
|
||||
}
|
||||
err = c.writeRequest(b)
|
||||
c.err = err
|
||||
@@ -212,12 +214,12 @@ func (c *EarlyWebsocketConn) Write(b []byte) (n int, err error) {
|
||||
|
||||
func (c *EarlyWebsocketConn) WriteBuffer(buffer *buf.Buffer) error {
|
||||
if c.conn != nil {
|
||||
return c.conn.WriteBuffer(buffer)
|
||||
return wrapWsError(c.conn.WriteBuffer(buffer))
|
||||
}
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
if c.conn != nil {
|
||||
return c.conn.WriteBuffer(buffer)
|
||||
return wrapWsError(c.conn.WriteBuffer(buffer))
|
||||
}
|
||||
if c.err != nil {
|
||||
return c.err
|
||||
@@ -272,3 +274,23 @@ func (c *EarlyWebsocketConn) Upstream() any {
|
||||
func (c *EarlyWebsocketConn) LazyHeadroom() bool {
|
||||
return c.conn == nil
|
||||
}
|
||||
|
||||
func wrapWsError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
var closedErr wsutil.ClosedError
|
||||
if errors.As(err, &closedErr) {
|
||||
if closedErr.Code == ws.StatusNormalClosure {
|
||||
err = io.EOF
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func wrapWsError0[T any](value T, err error) (T, error) {
|
||||
if err == nil {
|
||||
return value, nil
|
||||
}
|
||||
return value, wrapWsError(err)
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package v2raywebsocket
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
type deadConn struct {
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func (c *deadConn) SetDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *deadConn) SetReadDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *deadConn) SetWriteDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
@@ -66,7 +66,7 @@ func (w *Writer) WriteBuffer(buffer *buf.Buffer) error {
|
||||
ws.Cipher(data, *(*[4]byte)(header[1+payloadBitLength:]), 0)
|
||||
}
|
||||
|
||||
return w.writer.WriteBuffer(buffer)
|
||||
return wrapWsError(w.writer.WriteBuffer(buffer))
|
||||
}
|
||||
|
||||
func (w *Writer) FrontHeadroom() int {
|
||||
|
||||
Reference in New Issue
Block a user