Skip to content

Commit f366253

Browse files
committed
Add support for SideStore redirect
1 parent d3c7ff5 commit f366253

File tree

5 files changed

+64
-36
lines changed

5 files changed

+64
-36
lines changed

stack_gvisor.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,15 @@ const WithGVisor = true
2626
const DefaultNIC tcpip.NICID = 1
2727

2828
type GVisor struct {
29-
ctx context.Context
30-
tun GVisorTun
31-
udpTimeout time.Duration
32-
broadcastAddr netip.Addr
33-
handler Handler
34-
logger logger.Logger
35-
stack *stack.Stack
36-
endpoint stack.LinkEndpoint
29+
ctx context.Context
30+
tun GVisorTun
31+
udpTimeout time.Duration
32+
sideStoreRedirect bool
33+
broadcastAddr netip.Addr
34+
handler Handler
35+
logger logger.Logger
36+
stack *stack.Stack
37+
endpoint stack.LinkEndpoint
3738
}
3839

3940
type GVisorTun interface {
@@ -50,12 +51,13 @@ func NewGVisor(
5051
}
5152

5253
gStack := &GVisor{
53-
ctx: options.Context,
54-
tun: gTun,
55-
udpTimeout: options.UDPTimeout,
56-
broadcastAddr: BroadcastAddr(options.TunOptions.Inet4Address),
57-
handler: options.Handler,
58-
logger: options.Logger,
54+
ctx: options.Context,
55+
tun: gTun,
56+
udpTimeout: options.UDPTimeout,
57+
sideStoreRedirect: options.TunOptions.SideStoreRedirect,
58+
broadcastAddr: BroadcastAddr(options.TunOptions.Inet4Address),
59+
handler: options.Handler,
60+
logger: options.Logger,
5961
}
6062
return gStack, nil
6163
}
@@ -70,7 +72,7 @@ func (t *GVisor) Start() error {
7072
if err != nil {
7173
return err
7274
}
73-
ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, NewTCPForwarder(t.ctx, ipStack, t.handler).HandlePacket)
75+
ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, NewTCPForwarder(t.ctx, ipStack, t.handler, t.sideStoreRedirect, t.tun).HandlePacket)
7476
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, NewUDPForwarder(t.ctx, ipStack, t.handler, t.udpTimeout).HandlePacket)
7577
t.stack = ipStack
7678
t.endpoint = linkEndpoint

stack_gvisor_tcp.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,43 @@ package tun
55
import (
66
"context"
77

8+
"github.com/sagernet/gvisor/pkg/tcpip/header"
89
"github.com/sagernet/gvisor/pkg/tcpip/stack"
910
"github.com/sagernet/gvisor/pkg/tcpip/transport/tcp"
11+
"github.com/sagernet/sing/common/bufio"
1012
M "github.com/sagernet/sing/common/metadata"
1113
N "github.com/sagernet/sing/common/network"
1214
)
1315

1416
type TCPForwarder struct {
15-
ctx context.Context
16-
stack *stack.Stack
17-
handler Handler
18-
forwarder *tcp.Forwarder
17+
ctx context.Context
18+
stack *stack.Stack
19+
handler Handler
20+
sideStoreRedirect bool
21+
tun GVisorTun
22+
forwarder *tcp.Forwarder
1923
}
2024

21-
func NewTCPForwarder(ctx context.Context, stack *stack.Stack, handler Handler) *TCPForwarder {
25+
func NewTCPForwarder(ctx context.Context, stack *stack.Stack, handler Handler, sideStoreRedirect bool, tun GVisorTun) *TCPForwarder {
2226
forwarder := &TCPForwarder{
23-
ctx: ctx,
24-
stack: stack,
25-
handler: handler,
27+
ctx: ctx,
28+
tun: tun,
29+
stack: stack,
30+
handler: handler,
31+
sideStoreRedirect: sideStoreRedirect,
2632
}
2733
forwarder.forwarder = tcp.NewForwarder(stack, 0, 1024, forwarder.Forward)
2834
return forwarder
2935
}
3036

3137
func (f *TCPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.PacketBuffer) bool {
38+
if f.sideStoreRedirect && AddrFromAddress(id.LocalAddress) == sideStoreFakeIP && (id.RemotePort == sideStorePort || id.LocalPort == sideStorePort) {
39+
ipv4Hdr := pkt.Network().(header.IPv4)
40+
ipv4Hdr.SetDestinationAddressWithChecksumUpdate(ipv4Hdr.SourceAddress())
41+
ipv4Hdr.SetSourceAddressWithChecksumUpdate(AddressFromAddr(sideStoreFakeIP))
42+
bufio.WriteVectorised(f.tun, pkt.AsSlices())
43+
return true
44+
}
3245
return f.forwarder.HandlePacket(id, pkt)
3346
}
3447

stack_sidestore.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package tun
2+
3+
import "net/netip"
4+
5+
var (
6+
sideStoreFakeIP = netip.AddrFrom4([4]byte{10, 7, 0, 1})
7+
sideStorePort uint16 = 62078
8+
)

stack_system.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type System struct {
3636
inet6Address netip.Addr
3737
broadcastAddr netip.Addr
3838
udpTimeout time.Duration
39+
sideStoreRedirect bool
3940
tcpListener net.Listener
4041
tcpListener6 net.Listener
4142
tcpPort uint16
@@ -57,18 +58,19 @@ type Session struct {
5758

5859
func NewSystem(options StackOptions) (Stack, error) {
5960
stack := &System{
60-
ctx: options.Context,
61-
tun: options.Tun,
62-
tunName: options.TunOptions.Name,
63-
mtu: int(options.TunOptions.MTU),
64-
udpTimeout: options.UDPTimeout,
65-
handler: options.Handler,
66-
logger: options.Logger,
67-
inet4Prefixes: options.TunOptions.Inet4Address,
68-
inet6Prefixes: options.TunOptions.Inet6Address,
69-
broadcastAddr: BroadcastAddr(options.TunOptions.Inet4Address),
70-
bindInterface: options.ForwarderBindInterface,
71-
interfaceFinder: options.InterfaceFinder,
61+
ctx: options.Context,
62+
tun: options.Tun,
63+
tunName: options.TunOptions.Name,
64+
mtu: int(options.TunOptions.MTU),
65+
sideStoreRedirect: options.TunOptions.SideStoreRedirect,
66+
udpTimeout: options.UDPTimeout,
67+
handler: options.Handler,
68+
logger: options.Logger,
69+
inet4Prefixes: options.TunOptions.Inet4Address,
70+
inet6Prefixes: options.TunOptions.Inet6Address,
71+
broadcastAddr: BroadcastAddr(options.TunOptions.Inet4Address),
72+
bindInterface: options.ForwarderBindInterface,
73+
interfaceFinder: options.InterfaceFinder,
7274
}
7375
if len(options.TunOptions.Inet4Address) > 0 {
7476
if !HasNextAddress(options.TunOptions.Inet4Address[0], 1) {
@@ -351,6 +353,9 @@ func (s *System) processIPv4TCP(ipHdr header.IPv4, tcpHdr header.TCP) (bool, err
351353
tcpHdr.SetSourcePort(session.Destination.Port())
352354
ipHdr.SetDestinationAddr(session.Source.Addr())
353355
tcpHdr.SetDestinationPort(session.Source.Port())
356+
} else if s.sideStoreRedirect && destination.Addr() == sideStoreFakeIP && (source.Port() == sideStorePort || destination.Port() == sideStorePort) {
357+
ipHdr.SetDestinationAddr(ipHdr.SourceAddr())
358+
ipHdr.SetSourceAddr(sideStoreFakeIP)
354359
} else {
355360
natPort, err := s.tcpNat.Lookup(source, destination, s.handler)
356361
if err != nil {

tun.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ type Options struct {
7878
IncludeAndroidUser []int
7979
IncludePackage []string
8080
ExcludePackage []string
81+
SideStoreRedirect bool
8182
InterfaceFinder control.InterfaceFinder
8283
InterfaceMonitor DefaultInterfaceMonitor
8384
FileDescriptor int
8485
Logger logger.Logger
85-
8686
// No work for TCP, do not use.
8787
_TXChecksumOffload bool
8888

0 commit comments

Comments
 (0)