Skip to content

Commit bceb167

Browse files
colazcywindtf
andauthored
feat(resolve): add IP resolve strategy and format code (#181)
Co-authored-by: Wind Wong <im@windtfw.com>
1 parent 04030e8 commit bceb167

4 files changed

Lines changed: 108 additions & 44 deletions

File tree

cmd/wireproxy/main.go

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package main
33
import (
44
"context"
55
"fmt"
6-
"github.com/landlock-lsm/go-landlock/landlock"
76
"log"
87
"net"
98
"net/http"
@@ -13,6 +12,8 @@ import (
1312
"strconv"
1413
"syscall"
1514

15+
"github.com/landlock-lsm/go-landlock/landlock"
16+
1617
"github.com/akamensky/argparse"
1718
"github.com/pufferffish/wireproxy"
1819
"golang.zx2c4.com/wireguard/device"
@@ -23,9 +24,9 @@ import (
2324
const daemonProcess = "daemon-process"
2425

2526
// default paths for wireproxy config file
26-
var default_config_paths = []string {
27-
"/etc/wireproxy/wireproxy.conf",
28-
os.Getenv("HOME")+"/.config/wireproxy.conf",
27+
var default_config_paths = []string{
28+
"/etc/wireproxy/wireproxy.conf",
29+
os.Getenv("HOME") + "/.config/wireproxy.conf",
2930
}
3031

3132
var version = "1.0.8-dev"
@@ -59,12 +60,12 @@ func executablePath() string {
5960

6061
// check if default config file paths exist
6162
func configFilePath() (string, bool) {
62-
for _, path := range default_config_paths {
63-
if _, err := os.Stat(path); err == nil {
64-
return path, true
65-
}
66-
}
67-
return "", false
63+
for _, path := range default_config_paths {
64+
if _, err := os.Stat(path); err == nil {
65+
return path, true
66+
}
67+
}
68+
return "", false
6869
}
6970

7071
func lock(stage string) {
@@ -194,12 +195,12 @@ func main() {
194195
}
195196

196197
if *config == "" {
197-
if path, config_exist := configFilePath(); config_exist {
198-
*config = path
199-
} else {
200-
fmt.Println("configuration path is required")
201-
return
202-
}
198+
if path, config_exist := configFilePath(); config_exist {
199+
*config = path
200+
} else {
201+
fmt.Println("configuration path is required")
202+
return
203+
}
203204
}
204205

205206
if !*daemon {
@@ -245,7 +246,7 @@ func main() {
245246

246247
lock("ready")
247248

248-
tun, err := wireproxy.StartWireguard(conf.Device, logLevel)
249+
tun, err := wireproxy.StartWireguard(conf, logLevel)
249250
if err != nil {
250251
log.Fatal(err)
251252
}

config.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,14 @@ type HTTPConfig struct {
6969
KeyFile string
7070
}
7171

72+
type ResolveConfig struct {
73+
ResolveStrategy string
74+
}
75+
7276
type Configuration struct {
7377
Device *DeviceConfig
7478
Routines []RoutineSpawner
79+
Resolve *ResolveConfig
7580
}
7681

7782
func parseString(section *ini.Section, keyName string) (string, error) {
@@ -185,15 +190,15 @@ func parseCIDRNetIP(section *ini.Section, keyName string) ([]netip.Addr, error)
185190
if len(str) == 0 {
186191
continue
187192
}
188-
193+
189194
if addr, err := netip.ParseAddr(str); err == nil {
190195
ips = append(ips, addr)
191196
} else {
192197
prefix, err := netip.ParsePrefix(str)
193198
if err != nil {
194199
return nil, err
195200
}
196-
201+
197202
addr := prefix.Addr()
198203
ips = append(ips, addr)
199204
}
@@ -453,6 +458,15 @@ func parseHTTPConfig(section *ini.Section) (RoutineSpawner, error) {
453458
return config, nil
454459
}
455460

461+
func parseResolveConfig(section *ini.Section) (*ResolveConfig, error) {
462+
config := &ResolveConfig{}
463+
464+
resolvStrategy, _ := parseString(section, "ResolveStrategy")
465+
config.ResolveStrategy = resolvStrategy
466+
467+
return config, nil
468+
}
469+
456470
func parseUDPProxyTunnelConfig(section *ini.Section) (RoutineSpawner, error) {
457471
config := &UDPProxyTunnelConfig{}
458472

@@ -518,6 +532,10 @@ func ParseConfig(path string) (*Configuration, error) {
518532
MTU: 1420,
519533
}
520534

535+
resolve := &ResolveConfig{
536+
ResolveStrategy: "auto",
537+
}
538+
521539
root := cfg.Section("")
522540
wgConf, err := root.GetKey("WGConfig")
523541
wgCfg := cfg
@@ -565,6 +583,13 @@ func ParseConfig(path string) (*Configuration, error) {
565583
return nil, err
566584
}
567585

586+
if resolveSection, err := cfg.GetSection("Resolve"); err == nil {
587+
resolve, err = parseResolveConfig(resolveSection)
588+
if err != nil {
589+
return nil, err
590+
}
591+
}
592+
568593
err = parseRoutinesConfig(&routinesSpawners, cfg, "UDPProxyTunnel", parseUDPProxyTunnelConfig)
569594
if err != nil {
570595
return nil, err
@@ -573,5 +598,6 @@ func ParseConfig(path string) (*Configuration, error) {
573598
return &Configuration{
574599
Device: device,
575600
Routines: routinesSpawners,
601+
Resolve: resolve,
576602
}, nil
577603
}

routine.go

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ import (
88
"encoding/binary"
99
"encoding/json"
1010
"errors"
11-
"golang.org/x/net/icmp"
12-
"golang.org/x/net/ipv4"
13-
"golang.org/x/net/ipv6"
14-
"golang.zx2c4.com/wireguard/device"
1511
"io"
1612
"log"
1713
"math/rand"
@@ -24,6 +20,11 @@ import (
2420
"sync"
2521
"time"
2622

23+
"golang.org/x/net/icmp"
24+
"golang.org/x/net/ipv4"
25+
"golang.org/x/net/ipv6"
26+
"golang.zx2c4.com/wireguard/device"
27+
2728
"github.com/things-go/go-socks5"
2829
"github.com/things-go/go-socks5/bufferpool"
2930

@@ -43,10 +44,11 @@ type CredentialValidator struct {
4344

4445
// VirtualTun stores a reference to netstack network and DNS configuration
4546
type VirtualTun struct {
46-
Tnet *netstack.Net
47-
Dev *device.Device
48-
SystemDNS bool
49-
Conf *DeviceConfig
47+
Tnet *netstack.Net
48+
Dev *device.Device
49+
SystemDNS bool
50+
Conf *DeviceConfig
51+
ResolveConfig *ResolveConfig
5052
// PingRecord stores the last time an IP was pinged
5153
PingRecord map[string]uint64
5254
PingRecordLock *sync.Mutex
@@ -79,33 +81,48 @@ func (d VirtualTun) ResolveAddrWithContext(ctx context.Context, name string) (*n
7981
return nil, err
8082
}
8183

82-
size := len(addrs)
83-
if size == 0 {
84-
return nil, errors.New("no address found for: " + name)
85-
}
86-
87-
rand.Shuffle(size, func(i, j int) {
88-
addrs[i], addrs[j] = addrs[j], addrs[i]
89-
})
84+
addrs_v4 := []netip.Addr{}
85+
addrs_v6 := []netip.Addr{}
9086

91-
var addr netip.Addr
9287
for _, saddr := range addrs {
93-
addr, err = netip.ParseAddr(saddr)
88+
addr, err := netip.ParseAddr(saddr)
9489
if err == nil {
95-
break
90+
if addr.Is4() {
91+
addrs_v4 = append(addrs_v4, addr)
92+
} else if addr.Is6() {
93+
addrs_v6 = append(addrs_v6, addr)
94+
}
9695
}
9796
}
9897

99-
if err != nil {
100-
return nil, err
98+
rand.Shuffle(len(addrs_v4), func(i, j int) {
99+
addrs_v4[i], addrs_v4[j] = addrs_v4[j], addrs_v4[i]
100+
})
101+
rand.Shuffle(len(addrs_v6), func(i, j int) {
102+
addrs_v6[i], addrs_v6[j] = addrs_v6[j], addrs_v6[i]
103+
})
104+
105+
addrs_all := []netip.Addr{}
106+
107+
switch d.ResolveConfig.ResolveStrategy {
108+
case "ipv4":
109+
addrs_all = append(addrs_v4, addrs_v6...)
110+
case "ipv6":
111+
addrs_all = append(addrs_v6, addrs_v4...)
112+
}
113+
114+
if len(addrs_all) == 0 {
115+
return nil, errors.New("no address found for: " + name)
101116
}
102117

103-
return &addr, nil
118+
return &addrs_all[0], nil
104119
}
105120

106121
// Resolve resolves a hostname and returns an IP.
107122
// DNS traffic may or may not be routed depending on VirtualTun's setting
108123
func (d VirtualTun) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
124+
log.Printf("Resolving address for %s\n", name)
125+
109126
addr, err := d.ResolveAddrWithContext(ctx, name)
110127
if err != nil {
111128
return nil, nil, err

wireguard.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ func CreateIPCRequest(conf *DeviceConfig) (*DeviceSetting, error) {
6060
}
6161

6262
// StartWireguard creates a tun interface on netstack given a configuration
63-
func StartWireguard(conf *DeviceConfig, logLevel int) (*VirtualTun, error) {
64-
setting, err := CreateIPCRequest(conf)
63+
func StartWireguard(conf *Configuration, logLevel int) (*VirtualTun, error) {
64+
deviceConf := conf.Device
65+
setting, err := CreateIPCRequest(deviceConf)
6566
if err != nil {
6667
return nil, err
6768
}
@@ -81,10 +82,29 @@ func StartWireguard(conf *DeviceConfig, logLevel int) (*VirtualTun, error) {
8182
return nil, err
8283
}
8384

85+
hasV4 := false
86+
hasV6 := false
87+
for _, addr := range setting.DeviceAddr {
88+
if addr.Is4() {
89+
hasV4 = true
90+
}
91+
if addr.Is6() {
92+
hasV6 = true
93+
}
94+
}
95+
96+
if conf.Resolve.ResolveStrategy == "auto" {
97+
if hasV4 && !hasV6 {
98+
conf.Resolve.ResolveStrategy = "ipv4"
99+
} else {
100+
conf.Resolve.ResolveStrategy = "ipv6"
101+
}
102+
}
84103
return &VirtualTun{
85104
Tnet: tnet,
86105
Dev: dev,
87-
Conf: conf,
106+
Conf: deviceConf,
107+
ResolveConfig: conf.Resolve,
88108
SystemDNS: len(setting.DNS) == 0,
89109
PingRecord: make(map[string]uint64),
90110
PingRecordLock: new(sync.Mutex),

0 commit comments

Comments
 (0)