mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-10 12:24:13 +08:00
86 lines
2.0 KiB
Go
86 lines
2.0 KiB
Go
package wireguard
|
|
|
|
import (
|
|
"github.com/sagernet/sing-box/adapter"
|
|
"github.com/sagernet/sing-tun"
|
|
"github.com/sagernet/sing/common/buf"
|
|
)
|
|
|
|
var _ Device = (*natDeviceWrapper)(nil)
|
|
|
|
type natDeviceWrapper struct {
|
|
Device
|
|
gVisorOutbound
|
|
packetOutbound chan *buf.Buffer
|
|
mapping *tun.NatMapping
|
|
writer *tun.NatWriter
|
|
buffer [][]byte
|
|
}
|
|
|
|
func NewNATDevice(upstream Device, ipRewrite bool) NatDevice {
|
|
wrapper := &natDeviceWrapper{
|
|
Device: upstream,
|
|
gVisorOutbound: newGVisorOutbound(),
|
|
packetOutbound: make(chan *buf.Buffer, 256),
|
|
mapping: tun.NewNatMapping(ipRewrite),
|
|
}
|
|
if ipRewrite {
|
|
wrapper.writer = tun.NewNatWriter(upstream.Inet4Address(), upstream.Inet6Address())
|
|
}
|
|
return wrapper
|
|
}
|
|
|
|
func (d *natDeviceWrapper) Write(bufs [][]byte, offset int) (int, error) {
|
|
for _, buffer := range bufs {
|
|
handled, err := d.mapping.WritePacket(buffer[offset:])
|
|
if handled {
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
} else {
|
|
d.buffer = append(d.buffer, buffer)
|
|
}
|
|
}
|
|
if len(d.buffer) > 0 {
|
|
_, err := d.Device.Write(d.buffer, offset)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
d.buffer = d.buffer[:0]
|
|
}
|
|
return 0, nil
|
|
}
|
|
|
|
func (d *natDeviceWrapper) CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) {
|
|
session := tun.DirectRouteSession{
|
|
Source: metadata.Source.Addr,
|
|
Destination: metadata.Destination.Addr,
|
|
}
|
|
d.mapping.CreateSession(session, routeContext)
|
|
return &natDestinationWrapper{d, session}, nil
|
|
}
|
|
|
|
var _ tun.DirectRouteDestination = (*natDestinationWrapper)(nil)
|
|
|
|
type natDestinationWrapper struct {
|
|
device *natDeviceWrapper
|
|
session tun.DirectRouteSession
|
|
}
|
|
|
|
func (d *natDestinationWrapper) WritePacket(buffer *buf.Buffer) error {
|
|
if d.device.writer != nil {
|
|
d.device.writer.RewritePacket(buffer.Bytes())
|
|
}
|
|
d.device.packetOutbound <- buffer
|
|
return nil
|
|
}
|
|
|
|
func (d *natDestinationWrapper) Close() error {
|
|
d.device.mapping.DeleteSession(d.session)
|
|
return nil
|
|
}
|
|
|
|
func (d *natDestinationWrapper) Timeout() bool {
|
|
return false
|
|
}
|