Skip to content

Commit 0381a06

Browse files
committed
ping: Add destination rewriter
1 parent 960457a commit 0381a06

File tree

3 files changed

+88
-9
lines changed

3 files changed

+88
-9
lines changed

ping/destination_gvisor.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type GVisorDestination struct {
2727
logger logger.ContextLogger
2828
endpoint tcpip.Endpoint
2929
conn *gonet.TCPConn
30-
rewriter *Rewriter
30+
rewriter *SourceRewriter
3131
timeout time.Duration
3232
}
3333

@@ -76,7 +76,7 @@ func ConnectGVisor(
7676
return nil, gonet.TranslateNetstackError(gErr)
7777
}
7878
endpoint.SocketOptions().SetHeaderIncluded(true)
79-
rewriter := NewRewriter(ctx, logger, bindAddress4, bindAddress6)
79+
rewriter := NewSourceRewriter(ctx, logger, bindAddress4, bindAddress6)
8080
rewriter.CreateSession(tun.DirectRouteSession{Source: sourceAddress, Destination: destinationAddress}, routeContext)
8181
destination := &GVisorDestination{
8282
ctx: ctx,

ping/destination_rewriter.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package ping
2+
3+
import (
4+
"net/netip"
5+
6+
"github.com/sagernet/sing-tun"
7+
"github.com/sagernet/sing-tun/internal/gtcpip/header"
8+
"github.com/sagernet/sing/common/buf"
9+
)
10+
11+
type DestinationWriter struct {
12+
tun.DirectRouteDestination
13+
destination netip.Addr
14+
}
15+
16+
func NewDestinationWriter(routeDestination tun.DirectRouteDestination, destination netip.Addr) *DestinationWriter {
17+
return &DestinationWriter{routeDestination, destination}
18+
}
19+
20+
func (w *DestinationWriter) WritePacket(packet *buf.Buffer) error {
21+
var ipHdr header.Network
22+
switch header.IPVersion(packet.Bytes()) {
23+
case header.IPv4Version:
24+
ipHdr = header.IPv4(packet.Bytes())
25+
case header.IPv6Version:
26+
ipHdr = header.IPv6(packet.Bytes())
27+
default:
28+
return w.DirectRouteDestination.WritePacket(packet)
29+
}
30+
ipHdr.SetDestinationAddr(w.destination)
31+
if ipHdr4, isIPv4 := ipHdr.(header.IPv4); isIPv4 {
32+
ipHdr4.SetChecksum(^ipHdr4.CalculateChecksum())
33+
}
34+
if ipHdr.TransportProtocol() == header.ICMPv6ProtocolNumber {
35+
icmpHdr := header.ICMPv6(ipHdr.Payload())
36+
icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
37+
Header: icmpHdr,
38+
Src: ipHdr.SourceAddressSlice(),
39+
Dst: ipHdr.DestinationAddressSlice(),
40+
}))
41+
}
42+
return w.DirectRouteDestination.WritePacket(packet)
43+
}
44+
45+
type ContextDestinationWriter struct {
46+
tun.DirectRouteContext
47+
destination netip.Addr
48+
}
49+
50+
func NewContextDestinationWriter(context tun.DirectRouteContext, destination netip.Addr) *ContextDestinationWriter {
51+
return &ContextDestinationWriter{
52+
context, destination,
53+
}
54+
}
55+
56+
func (w *ContextDestinationWriter) WritePacket(packet []byte) error {
57+
var ipHdr header.Network
58+
switch header.IPVersion(packet) {
59+
case header.IPv4Version:
60+
ipHdr = header.IPv4(packet)
61+
case header.IPv6Version:
62+
ipHdr = header.IPv6(packet)
63+
default:
64+
return w.DirectRouteContext.WritePacket(packet)
65+
}
66+
ipHdr.SetSourceAddr(w.destination)
67+
if ipHdr4, isIPv4 := ipHdr.(header.IPv4); isIPv4 {
68+
ipHdr4.SetChecksum(^ipHdr4.CalculateChecksum())
69+
}
70+
if ipHdr.TransportProtocol() == header.ICMPv6ProtocolNumber {
71+
icmpHdr := header.ICMPv6(ipHdr.Payload())
72+
icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
73+
Header: icmpHdr,
74+
Src: ipHdr.SourceAddressSlice(),
75+
Dst: ipHdr.DestinationAddressSlice(),
76+
}))
77+
}
78+
return w.DirectRouteContext.WritePacket(packet)
79+
}

ping/rewriter.go renamed to ping/source_rewriter.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"github.com/sagernet/sing/common/logger"
1111
)
1212

13-
type Rewriter struct {
13+
type SourceRewriter struct {
1414
ctx context.Context
1515
logger logger.ContextLogger
1616
access sync.RWMutex
@@ -20,8 +20,8 @@ type Rewriter struct {
2020
inet6Address netip.Addr
2121
}
2222

23-
func NewRewriter(ctx context.Context, logger logger.ContextLogger, inet4Address netip.Addr, inet6Address netip.Addr) *Rewriter {
24-
return &Rewriter{
23+
func NewSourceRewriter(ctx context.Context, logger logger.ContextLogger, inet4Address netip.Addr, inet6Address netip.Addr) *SourceRewriter {
24+
return &SourceRewriter{
2525
ctx: ctx,
2626
logger: logger,
2727
sessions: make(map[tun.DirectRouteSession]tun.DirectRouteContext),
@@ -31,19 +31,19 @@ func NewRewriter(ctx context.Context, logger logger.ContextLogger, inet4Address
3131
}
3232
}
3333

34-
func (m *Rewriter) CreateSession(session tun.DirectRouteSession, context tun.DirectRouteContext) {
34+
func (m *SourceRewriter) CreateSession(session tun.DirectRouteSession, context tun.DirectRouteContext) {
3535
m.access.Lock()
3636
m.sessions[session] = context
3737
m.access.Unlock()
3838
}
3939

40-
func (m *Rewriter) DeleteSession(session tun.DirectRouteSession) {
40+
func (m *SourceRewriter) DeleteSession(session tun.DirectRouteSession) {
4141
m.access.Lock()
4242
delete(m.sessions, session)
4343
m.access.Unlock()
4444
}
4545

46-
func (m *Rewriter) RewritePacket(packet []byte) {
46+
func (m *SourceRewriter) RewritePacket(packet []byte) {
4747
var ipHdr header.Network
4848
var bindAddr netip.Addr
4949
switch header.IPVersion(packet) {
@@ -82,7 +82,7 @@ func (m *Rewriter) RewritePacket(packet []byte) {
8282
}
8383
}
8484

85-
func (m *Rewriter) WriteBack(packet []byte) (bool, error) {
85+
func (m *SourceRewriter) WriteBack(packet []byte) (bool, error) {
8686
var ipHdr header.Network
8787
var routeSession tun.DirectRouteSession
8888
switch header.IPVersion(packet) {

0 commit comments

Comments
 (0)