| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- //go:build with_gvisor && !windows
- package tailscale
- import (
- "encoding/hex"
- "errors"
- "io"
- "os"
- "sync"
- "sync/atomic"
- singTun "github.com/sagernet/sing-tun"
- "github.com/sagernet/sing/common"
- "github.com/sagernet/sing/common/logger"
- wgTun "github.com/sagernet/wireguard-go/tun"
- )
- type tunDeviceAdapter struct {
- tun singTun.Tun
- linuxTUN singTun.LinuxTUN
- events chan wgTun.Event
- mtu int
- logger logger.ContextLogger
- debugTun bool
- readCount atomic.Uint32
- writeCount atomic.Uint32
- closeOnce sync.Once
- }
- func newTunDeviceAdapter(tun singTun.Tun, mtu int, logger logger.ContextLogger) (wgTun.Device, error) {
- if tun == nil {
- return nil, os.ErrInvalid
- }
- if mtu == 0 {
- mtu = 1500
- }
- adapter := &tunDeviceAdapter{
- tun: tun,
- events: make(chan wgTun.Event, 1),
- mtu: mtu,
- logger: logger,
- debugTun: os.Getenv("SINGBOX_TS_TUN_DEBUG") != "",
- }
- if linuxTUN, ok := tun.(singTun.LinuxTUN); ok {
- adapter.linuxTUN = linuxTUN
- }
- adapter.events <- wgTun.EventUp
- return adapter, nil
- }
- func (a *tunDeviceAdapter) File() *os.File {
- return nil
- }
- func (a *tunDeviceAdapter) Read(bufs [][]byte, sizes []int, offset int) (count int, err error) {
- if a.linuxTUN != nil {
- n, err := a.linuxTUN.BatchRead(bufs, offset-singTun.PacketOffset, sizes)
- if err == nil {
- for i := 0; i < n; i++ {
- a.debugPacket("read", bufs[i][offset:offset+sizes[i]])
- }
- }
- return n, err
- }
- if offset < singTun.PacketOffset {
- return 0, io.ErrShortBuffer
- }
- readBuf := bufs[0][offset-singTun.PacketOffset:]
- n, err := a.tun.Read(readBuf)
- if err == nil {
- if n < singTun.PacketOffset {
- return 0, io.ErrUnexpectedEOF
- }
- sizes[0] = n - singTun.PacketOffset
- a.debugPacket("read", readBuf[singTun.PacketOffset:n])
- return 1, nil
- }
- if errors.Is(err, singTun.ErrTooManySegments) {
- err = wgTun.ErrTooManySegments
- }
- return 0, err
- }
- func (a *tunDeviceAdapter) Write(bufs [][]byte, offset int) (count int, err error) {
- if a.linuxTUN != nil {
- for i := range bufs {
- a.debugPacket("write", bufs[i][offset:])
- }
- return a.linuxTUN.BatchWrite(bufs, offset)
- }
- for _, packet := range bufs {
- a.debugPacket("write", packet[offset:])
- if singTun.PacketOffset > 0 {
- common.ClearArray(packet[offset-singTun.PacketOffset : offset])
- singTun.PacketFillHeader(packet[offset-singTun.PacketOffset:], singTun.PacketIPVersion(packet[offset:]))
- }
- _, err = a.tun.Write(packet[offset-singTun.PacketOffset:])
- if err != nil {
- return 0, err
- }
- }
- // WireGuard will not read count.
- return 0, nil
- }
- func (a *tunDeviceAdapter) MTU() (int, error) {
- return a.mtu, nil
- }
- func (a *tunDeviceAdapter) Name() (string, error) {
- return a.tun.Name()
- }
- func (a *tunDeviceAdapter) Events() <-chan wgTun.Event {
- return a.events
- }
- func (a *tunDeviceAdapter) Close() error {
- var err error
- a.closeOnce.Do(func() {
- close(a.events)
- err = a.tun.Close()
- })
- return err
- }
- func (a *tunDeviceAdapter) BatchSize() int {
- if a.linuxTUN != nil {
- return a.linuxTUN.BatchSize()
- }
- return 1
- }
- func (a *tunDeviceAdapter) debugPacket(direction string, packet []byte) {
- if !a.debugTun || a.logger == nil {
- return
- }
- var counter *atomic.Uint32
- switch direction {
- case "read":
- counter = &a.readCount
- case "write":
- counter = &a.writeCount
- default:
- return
- }
- if counter.Add(1) > 8 {
- return
- }
- sample := packet
- if len(sample) > 64 {
- sample = sample[:64]
- }
- a.logger.Trace("tailscale tun ", direction, " len=", len(packet), " head=", hex.EncodeToString(sample))
- }
|