-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtun.go
120 lines (105 loc) · 2.32 KB
/
tun.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package tun
import (
"io"
"net"
"net/netip"
"runtime"
"strconv"
"strings"
N "github.com/josexy/cropstun/common/network"
)
type Metadata struct {
Source netip.AddrPort
Destination netip.AddrPort
}
type TCPConn interface {
net.Conn
}
type UDPConn interface {
net.Conn
net.PacketConn
}
type TCPConnectionHandler interface {
HandleTCPConnection(TCPConn, Metadata) error
}
type UDPConnectionHandler interface {
HandleUDPConnection(UDPConn, Metadata) error
}
type Handler interface {
TCPConnectionHandler
UDPConnectionHandler
}
type Tun interface {
io.ReadWriteCloser
N.VectorisedWriter
SetupDNS([]netip.Addr) error
TeardownDNS() error
}
type WinTun interface {
Tun
ReadPacket() ([]byte, func(), error)
}
type LinuxTUN interface {
Tun
TXChecksumOffload() bool
}
const (
DefaultMTU = 9000
DefaultIPRoute2TableIndex = 4000
DefaultIPRoute2RuleIndex = 10086
)
type Options struct {
Name string
Inet4Address []netip.Prefix
Inet6Address []netip.Prefix
MTU uint32
IPRoute2TableIndex int
IPRoute2RuleIndex int
AutoRoute bool
}
func NewTunDevice(cidrs []netip.Prefix, options *Options) (Tun, error) {
if options.Name == "" {
options.Name = CalculateInterfaceName(options.Name)
}
if options.MTU == 0 {
options.MTU = DefaultMTU
}
if options.IPRoute2TableIndex <= 0 {
options.IPRoute2TableIndex = DefaultIPRoute2TableIndex
}
if options.IPRoute2RuleIndex <= 0 {
options.IPRoute2RuleIndex = DefaultIPRoute2RuleIndex
}
for _, cidr := range cidrs {
if cidr.Addr().Is4() {
options.Inet4Address = append(options.Inet4Address, cidr)
} else if cidr.Addr().Is6() {
options.Inet6Address = append(options.Inet6Address, cidr)
}
}
return New(options)
}
func CalculateInterfaceName(name string) (tunName string) {
if runtime.GOOS == "darwin" {
tunName = "utun"
} else if name != "" {
tunName = name
} else {
tunName = "tun"
}
interfaces, err := net.Interfaces()
if err != nil {
return
}
var tunIndex int
for _, netInterface := range interfaces {
if strings.HasPrefix(netInterface.Name, tunName) {
index, parseErr := strconv.ParseInt(netInterface.Name[len(tunName):], 10, 16)
if parseErr == nil && int(index) >= tunIndex {
tunIndex = int(index) + 1
}
}
}
tunName = tunName + strconv.FormatInt(int64(tunIndex), 10)
return
}