-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhmvpn-client-demo.go
155 lines (133 loc) · 3.74 KB
/
hmvpn-client-demo.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package main
import (
"flag"
"fmt"
"log"
"net"
"os"
"syscall"
"unsafe"
)
const (
// tun设备文件
tunDeviceFile = "/dev/net/tun"
// tun设备名称
tunDeviceName = "tun1"
// 默认MTU为1500,此处用作数据buffer大小
// 一个IP头(20字节)和一个UDP头(8)字节。如果f设置1500,
// 加上IP和UDP头的28字节数据,到达宿主机eth0的时候最大报文会超过eth0的MTU,eth0会把该数据包丢弃
defaultMTU = 1472
udpPort = 8285
)
var dstUDPHost = flag.String("d", "127.0.0.1:8285", "destination UDP host")
type ifReq struct {
name [16]byte
flags uint16
}
func main() {
flag.Parse()
// 初始化tun设备
conn, sErr := SendUDPData()
if sErr != nil {
log.Printf("initSocket error: %s", sErr.Error())
return
}
defer conn.Close()
log.Printf("send data success")
tun, tErr := InitTunDevice()
if tErr != nil {
log.Printf("initTunDevice error: %s", tErr.Error())
return
}
defer tun.Close()
log.Printf("initTunDevice tun with file %s success", tunDeviceFile)
Tun2Socket(tun, conn)
}
func InitTunDevice() (*os.File, error) {
// 打开tun设备文件
tun, err := os.OpenFile(tunDeviceFile, os.O_RDWR, 0)
if err != nil {
return nil, fmt.Errorf("os.OpenFile error: %s", err.Error())
}
// ioctl设置
var ir = ifReq{
flags: syscall.IFF_TUN | syscall.IFF_NO_PI,
}
copy(ir.name[:], tunDeviceName)
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, tun.Fd(), syscall.TUNSETIFF, uintptr(unsafe.Pointer(&ir)))
if errno != 0 {
return nil, fmt.Errorf("ioctl error: expect 0 but got %d", errno)
}
log.Printf("ioctl success")
return tun, nil
}
// func Socket2Tun(conn *net.UDPConn, tun *os.File) {
// var buffer = make([]byte, defaultMTU)
// for {
// cn, remoteAddr, err := conn.ReadFromUDP(buffer)
// if err != nil {
// fmt.Printf("conn.ReadFromUDP err:[%v]\n", err)
// }
// // defer conn.Close()
// log.Printf("read %d bytes data from udp %s", cn, remoteAddr)
// // 接收数据
// // go handler(buffer[:n])
// data := buffer[:cn]
// // _, err = conn.WriteToUDP(data, remoteAddr)
// tn, err := tun.Write(data)
// if err != nil {
// log.Printf("handler write data to tun device error: %s", err.Error())
// return
// }
// log.Printf("handler write %d bytes data to tun device", tn)
// }
// }
func Tun2Socket(tun *os.File, conn *net.UDPConn) {
buffer := make([]byte, defaultMTU)
for {
tn, tErr := tun.Read(buffer)
if tErr != nil {
log.Printf("read data from tun error: %s", tErr.Error())
return
}
log.Panicf("read %d byte data from tun device", tn)
// data := buffer[:tn]
// conn.remoteAddr()
cn, cErr := conn.Write(buffer)
// return conn.Write(data)
if cErr != nil {
log.Printf("handler write data to tun device error: %s", cErr.Error())
return
}
log.Printf("handler write %d bytes data to tun device", cn)
}
}
// UDPServer 接收UDP数据
// func UDPServer(handler func(data []byte))
// func UDPServer() (*net.UDPConn, error) {
// updServerHost := fmt.Sprintf(":%d", udpPort)
// conn, err := net.ListenUDP("udp", &net.UDPAddr{
// IP: net.IPv4(0, 0, 0, 0),
// Port: udpPort,
// })
// if err != nil {
// log.Fatalf("net.Listen error: %s", err.Error())
// }
// // defer conn.Close()
// log.Printf("udp listen on: %s", updServerHost)
// return conn, nil
// }
func SendUDPData() (*net.UDPConn, error) {
serverAddr, err := net.ResolveUDPAddr("udp", *dstUDPHost)
if err != nil {
log.Fatalln("failed to resolve server addr:", err)
}
conn, err := net.DialUDP("udp", nil, serverAddr)
if err != nil {
fmt.Errorf("net.Dial error: %s", err.Error())
}
log.Printf("dialUDP to %s success serverAddr", serverAddr)
log.Printf("dialUDP to %s success conn.RemoteAddr()", conn.RemoteAddr())
// return conn.Write(data)
return conn, nil
}