ping: Add destination rewriter
This commit is contained in:
parent
960457abba
commit
0381a06643
3 changed files with 88 additions and 9 deletions
|
|
@ -27,7 +27,7 @@ type GVisorDestination struct {
|
||||||
logger logger.ContextLogger
|
logger logger.ContextLogger
|
||||||
endpoint tcpip.Endpoint
|
endpoint tcpip.Endpoint
|
||||||
conn *gonet.TCPConn
|
conn *gonet.TCPConn
|
||||||
rewriter *Rewriter
|
rewriter *SourceRewriter
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ func ConnectGVisor(
|
||||||
return nil, gonet.TranslateNetstackError(gErr)
|
return nil, gonet.TranslateNetstackError(gErr)
|
||||||
}
|
}
|
||||||
endpoint.SocketOptions().SetHeaderIncluded(true)
|
endpoint.SocketOptions().SetHeaderIncluded(true)
|
||||||
rewriter := NewRewriter(ctx, logger, bindAddress4, bindAddress6)
|
rewriter := NewSourceRewriter(ctx, logger, bindAddress4, bindAddress6)
|
||||||
rewriter.CreateSession(tun.DirectRouteSession{Source: sourceAddress, Destination: destinationAddress}, routeContext)
|
rewriter.CreateSession(tun.DirectRouteSession{Source: sourceAddress, Destination: destinationAddress}, routeContext)
|
||||||
destination := &GVisorDestination{
|
destination := &GVisorDestination{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
|
|
|
||||||
79
ping/destination_rewriter.go
Normal file
79
ping/destination_rewriter.go
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
package ping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-tun"
|
||||||
|
"github.com/sagernet/sing-tun/internal/gtcpip/header"
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DestinationWriter struct {
|
||||||
|
tun.DirectRouteDestination
|
||||||
|
destination netip.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDestinationWriter(routeDestination tun.DirectRouteDestination, destination netip.Addr) *DestinationWriter {
|
||||||
|
return &DestinationWriter{routeDestination, destination}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *DestinationWriter) WritePacket(packet *buf.Buffer) error {
|
||||||
|
var ipHdr header.Network
|
||||||
|
switch header.IPVersion(packet.Bytes()) {
|
||||||
|
case header.IPv4Version:
|
||||||
|
ipHdr = header.IPv4(packet.Bytes())
|
||||||
|
case header.IPv6Version:
|
||||||
|
ipHdr = header.IPv6(packet.Bytes())
|
||||||
|
default:
|
||||||
|
return w.DirectRouteDestination.WritePacket(packet)
|
||||||
|
}
|
||||||
|
ipHdr.SetDestinationAddr(w.destination)
|
||||||
|
if ipHdr4, isIPv4 := ipHdr.(header.IPv4); isIPv4 {
|
||||||
|
ipHdr4.SetChecksum(^ipHdr4.CalculateChecksum())
|
||||||
|
}
|
||||||
|
if ipHdr.TransportProtocol() == header.ICMPv6ProtocolNumber {
|
||||||
|
icmpHdr := header.ICMPv6(ipHdr.Payload())
|
||||||
|
icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
|
||||||
|
Header: icmpHdr,
|
||||||
|
Src: ipHdr.SourceAddressSlice(),
|
||||||
|
Dst: ipHdr.DestinationAddressSlice(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
return w.DirectRouteDestination.WritePacket(packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContextDestinationWriter struct {
|
||||||
|
tun.DirectRouteContext
|
||||||
|
destination netip.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewContextDestinationWriter(context tun.DirectRouteContext, destination netip.Addr) *ContextDestinationWriter {
|
||||||
|
return &ContextDestinationWriter{
|
||||||
|
context, destination,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *ContextDestinationWriter) WritePacket(packet []byte) error {
|
||||||
|
var ipHdr header.Network
|
||||||
|
switch header.IPVersion(packet) {
|
||||||
|
case header.IPv4Version:
|
||||||
|
ipHdr = header.IPv4(packet)
|
||||||
|
case header.IPv6Version:
|
||||||
|
ipHdr = header.IPv6(packet)
|
||||||
|
default:
|
||||||
|
return w.DirectRouteContext.WritePacket(packet)
|
||||||
|
}
|
||||||
|
ipHdr.SetSourceAddr(w.destination)
|
||||||
|
if ipHdr4, isIPv4 := ipHdr.(header.IPv4); isIPv4 {
|
||||||
|
ipHdr4.SetChecksum(^ipHdr4.CalculateChecksum())
|
||||||
|
}
|
||||||
|
if ipHdr.TransportProtocol() == header.ICMPv6ProtocolNumber {
|
||||||
|
icmpHdr := header.ICMPv6(ipHdr.Payload())
|
||||||
|
icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
|
||||||
|
Header: icmpHdr,
|
||||||
|
Src: ipHdr.SourceAddressSlice(),
|
||||||
|
Dst: ipHdr.DestinationAddressSlice(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
return w.DirectRouteContext.WritePacket(packet)
|
||||||
|
}
|
||||||
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/sagernet/sing/common/logger"
|
"github.com/sagernet/sing/common/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Rewriter struct {
|
type SourceRewriter struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
logger logger.ContextLogger
|
logger logger.ContextLogger
|
||||||
access sync.RWMutex
|
access sync.RWMutex
|
||||||
|
|
@ -20,8 +20,8 @@ type Rewriter struct {
|
||||||
inet6Address netip.Addr
|
inet6Address netip.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRewriter(ctx context.Context, logger logger.ContextLogger, inet4Address netip.Addr, inet6Address netip.Addr) *Rewriter {
|
func NewSourceRewriter(ctx context.Context, logger logger.ContextLogger, inet4Address netip.Addr, inet6Address netip.Addr) *SourceRewriter {
|
||||||
return &Rewriter{
|
return &SourceRewriter{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
sessions: make(map[tun.DirectRouteSession]tun.DirectRouteContext),
|
sessions: make(map[tun.DirectRouteSession]tun.DirectRouteContext),
|
||||||
|
|
@ -31,19 +31,19 @@ func NewRewriter(ctx context.Context, logger logger.ContextLogger, inet4Address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Rewriter) CreateSession(session tun.DirectRouteSession, context tun.DirectRouteContext) {
|
func (m *SourceRewriter) CreateSession(session tun.DirectRouteSession, context tun.DirectRouteContext) {
|
||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
m.sessions[session] = context
|
m.sessions[session] = context
|
||||||
m.access.Unlock()
|
m.access.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Rewriter) DeleteSession(session tun.DirectRouteSession) {
|
func (m *SourceRewriter) DeleteSession(session tun.DirectRouteSession) {
|
||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
delete(m.sessions, session)
|
delete(m.sessions, session)
|
||||||
m.access.Unlock()
|
m.access.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Rewriter) RewritePacket(packet []byte) {
|
func (m *SourceRewriter) RewritePacket(packet []byte) {
|
||||||
var ipHdr header.Network
|
var ipHdr header.Network
|
||||||
var bindAddr netip.Addr
|
var bindAddr netip.Addr
|
||||||
switch header.IPVersion(packet) {
|
switch header.IPVersion(packet) {
|
||||||
|
|
@ -82,7 +82,7 @@ func (m *Rewriter) RewritePacket(packet []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Rewriter) WriteBack(packet []byte) (bool, error) {
|
func (m *SourceRewriter) WriteBack(packet []byte) (bool, error) {
|
||||||
var ipHdr header.Network
|
var ipHdr header.Network
|
||||||
var routeSession tun.DirectRouteSession
|
var routeSession tun.DirectRouteSession
|
||||||
switch header.IPVersion(packet) {
|
switch header.IPVersion(packet) {
|
||||||
Loading…
Add table
Add a link
Reference in a new issue