-
Notifications
You must be signed in to change notification settings - Fork 10
/
client.go
112 lines (103 loc) · 3.55 KB
/
client.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
package mwgp
import (
"context"
"fmt"
"golang.zx2c4.com/wireguard/device"
"log"
"net"
"time"
)
type ClientConfig struct {
Server string `json:"server"`
Listen string `json:"listen"`
Timeout int `json:"timeout,omitempty"`
Resolver string `json:"resolver,omitempty"`
ClientSourceValidateLevel int `json:"csvl,omitempty"`
ServerSourceValidateLevel int `json:"ssvl,omitempty"`
MaxPacketSize int `json:"max_packet_size,omitempty"`
ClientPublicKey NoisePublicKey `json:"client_pubkey"`
ServerPublicKey NoisePublicKey `json:"server_pubkey"`
ObfuscateKey string `json:"obfs"`
WGITCacheConfig
// Deprecated: use Resolver instead
DNS string `json:"dns,omitempty"`
}
type Client struct {
wgitTable *WireGuardIndexTranslationTable
server string
cachedServerPeer ServerConfigPeer
resolver UDPAddrResolver
}
func NewClientWithConfig(config *ClientConfig) (outClient *Client, err error) {
client := Client{}
client.server = config.Server
client.wgitTable = NewWireGuardIndexTranslationTable()
client.wgitTable.ClientListen, err = net.ResolveUDPAddr("udp", config.Listen)
if err != nil {
err = fmt.Errorf("invalid listen address %s: %w", config.Listen, err)
return
}
if config.Timeout > 0 {
client.wgitTable.Timeout = time.Duration(config.Timeout) * time.Second
}
if config.MaxPacketSize > 0 {
client.wgitTable.MaxPacketSize = uint(config.MaxPacketSize)
}
client.wgitTable.ExtractPeerFunc = client.generateServerPeer
client.cachedServerPeer.serverPublicKey = config.ServerPublicKey
client.cachedServerPeer.ClientPublicKey = &config.ClientPublicKey
client.wgitTable.CacheJar.WGITCacheConfig = config.WGITCacheConfig
resolver := config.Resolver
if config.DNS != "" {
if resolver == "" {
resolver = fmt.Sprintf("dns+udp://%s", config.DNS)
} else {
err = fmt.Errorf("option \"dns\" and \"resolver\" is conflicted with each other")
return
}
}
client.resolver, err = newUDPAddrResolver(resolver)
if err != nil {
err = fmt.Errorf("failed to create resolver: %w", err)
return
}
var obfuscator WireGuardObfuscator
obfuscator.Initialize(config.ObfuscateKey)
client.wgitTable.ServerWriteToUDPFunc = func(conn *net.UDPConn, packet *Packet) (err error) {
packet.Flags |= PacketFlagObfuscateBeforeSend
return obfuscator.WriteToUDPWithObfuscate(conn, packet)
}
client.wgitTable.ServerReadFromUDPFunc = obfuscator.ReadFromUDPWithDeobfuscate
outClient = &client
return
}
func (c *Client) generateServerPeer(msg *device.MessageInitiation) (fi *ServerConfigPeer, err error) {
if c.cachedServerPeer.forwardToAddress == nil {
err = fmt.Errorf("forward_to address is not resolved yet")
return
}
fi = &c.cachedServerPeer
return
}
func (c *Client) Start() (err error) {
go func() {
for {
sa, rerr := c.resolver.ResolveUDPAddr(context.Background(), c.server)
if rerr != nil {
log.Printf("[error] failed to resolve server addr %s: %s, retry in 10 seconds", c.server, rerr.Error())
time.Sleep(10 * time.Second)
continue
}
if c.cachedServerPeer.forwardToAddress == nil ||
!c.cachedServerPeer.forwardToAddress.IP.Equal(sa.IP) ||
c.cachedServerPeer.forwardToAddress.Port != sa.Port {
c.cachedServerPeer.forwardToAddress = sa
c.wgitTable.UpdateAllServerDestinationChan <- sa
}
time.Sleep(5 * time.Minute)
}
}()
log.Printf("[info] listen on %s ...\n", c.wgitTable.ClientListen)
err = c.wgitTable.Serve()
return
}