Skip to content

Commit 0453b91

Browse files
committed
app: add DisableVPNInterface option
1 parent af96d8d commit 0453b91

9 files changed

Lines changed: 111 additions & 32 deletions

File tree

api/settings.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ func (h *Handler) GetMyPeerInfo(c echo.Context) (err error) {
3131
Reachability: h.p2p.Reachability().String(),
3232
AwlDNSAddress: h.dns.AwlDNSAddress(),
3333
IsAwlDNSSetAsSystem: h.dns.IsAwlDNSSetAsSystem(),
34+
VPN: entity.VPNInfo{
35+
VPNInterfaceEnabled: h.tunnel != nil,
36+
InterfaceName: h.conf.VPNConfig.InterfaceName,
37+
IPNet: h.conf.VPNConfig.IPNet,
38+
},
3439
SOCKS5: entity.SOCKS5Info{
3540
ListenAddress: h.conf.SOCKS5.ListenAddress,
3641
ProxyingEnabled: h.conf.SOCKS5.ProxyingEnabled,

application.go

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -105,34 +105,42 @@ func (a *Application) Init(ctx context.Context, tunDevice tun.Device) error {
105105
a.logger.Infof("P2P host initialized. My peer_id: %s", p2pHost.ID().String())
106106
a.logger.Infof("P2P listening on addresses: %v", p2pHost.Addrs())
107107

108-
localIP, netMask := a.Conf.VPNLocalIPMask()
109-
interfaceName := a.Conf.VPNConfig.InterfaceName
110-
vpnDevice, err := vpn.NewDevice(tunDevice, interfaceName, localIP, netMask)
111-
if err != nil {
112-
return fmt.Errorf("failed to init vpn: %v", err)
108+
if a.Conf.VPNConfig.DisableVPNInterface {
109+
a.logger.Info("VPN interface is disabled from config")
110+
} else {
111+
localIP, netMask := a.Conf.VPNLocalIPMask()
112+
interfaceName := a.Conf.VPNConfig.InterfaceName
113+
a.vpnDevice, err = vpn.NewDevice(tunDevice, interfaceName, localIP, netMask)
114+
if err != nil {
115+
return fmt.Errorf("failed to init vpn: %v", err)
116+
}
117+
a.logger.Infof("VPN interface created. Name: %s CIDR: %s", interfaceName, &net.IPNet{IP: localIP, Mask: netMask})
118+
119+
a.Tunnel = service.NewTunnel(a.P2p, a.vpnDevice, a.Conf)
120+
go a.vpnDevice.ReadTUNPackets(a.Tunnel.HandleReadPackets)
113121
}
114-
a.vpnDevice = vpnDevice
115-
a.logger.Infof("VPN interface created. Name: %s CIDR: %s", interfaceName, &net.IPNet{IP: localIP, Mask: netMask})
116122

117123
a.P2p.Bootstrap()
118124

119125
a.Dns = NewDNSService(a.Conf, a.Eventbus, a.ctx, a.logger)
120126
a.AuthStatus = service.NewAuthStatus(a.P2p, a.Conf, a.Eventbus)
121-
a.Tunnel = service.NewTunnel(a.P2p, vpnDevice, a.Conf)
122-
go vpnDevice.ReadTUNPackets(a.Tunnel.HandleReadPackets)
123127
a.SOCKS5, err = service.NewSOCKS5(a.P2p, a.Conf)
124128
if err != nil {
125129
return fmt.Errorf("failed to init socks5: %v", err)
126130
}
127131

128132
p2pHost.SetStreamHandler(protocol.GetStatusMethod, a.AuthStatus.StatusStreamHandler)
129133
p2pHost.SetStreamHandler(protocol.AuthMethod, a.AuthStatus.AuthStreamHandler)
130-
p2pHost.SetStreamHandler(protocol.TunnelPacketMethod, a.Tunnel.StreamHandler)
134+
if a.Tunnel != nil {
135+
p2pHost.SetStreamHandler(protocol.TunnelPacketMethod, a.Tunnel.StreamHandler)
136+
}
131137
p2pHost.SetStreamHandler(protocol.Socks5PacketMethod, a.SOCKS5.ProxyStreamHandler)
132138

133-
awlevent.WrapSubscriptionToCallback(a.ctx, func(_ interface{}) {
134-
a.Tunnel.RefreshPeersList()
135-
}, a.Eventbus, new(awlevent.KnownPeerChanged))
139+
if a.Tunnel != nil {
140+
awlevent.WrapSubscriptionToCallback(a.ctx, func(_ interface{}) {
141+
a.Tunnel.RefreshPeersList()
142+
}, a.Eventbus, new(awlevent.KnownPeerChanged))
143+
}
136144

137145
handler := api.NewHandler(a.Conf, a.P2p, a.AuthStatus, a.Tunnel, a.SOCKS5, a.LogBuffer, a.Dns)
138146
a.Api = handler
@@ -146,7 +154,7 @@ func (a *Application) Init(ctx context.Context, tunDevice tun.Device) error {
146154
go a.AuthStatus.BackgroundExchangeStatusInfo(a.ctx)
147155
go a.SOCKS5.ServeConns(a.ctx)
148156

149-
if useAwldns {
157+
if useAwldns && !a.Conf.VPNConfig.DisableVPNInterface {
150158
interfaceName, err := a.vpnDevice.InterfaceName()
151159
if err != nil {
152160
a.logger.Errorf("failed to get TUN interface name: %v", err)

application_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,45 @@ func TestUpdatePeerSettingsIPAddr(t *testing.T) {
703703
})
704704
}
705705

706+
func TestDisableVPNInterface(t *testing.T) {
707+
ts := NewTestSuite(t)
708+
709+
peer1 := ts.NewTestPeer(false)
710+
711+
// Create peer2 with disabled VPN
712+
peer2 := ts.NewTestPeerWithConfig(func(c *config.Config) {
713+
c.VPNConfig.DisableVPNInterface = true
714+
})
715+
716+
// Verify peer2 has no VPN/Tunnel
717+
ts.Nil(peer2.app.vpnDevice)
718+
ts.Nil(peer2.app.Tunnel)
719+
peer2Status, err := peer2.api.PeerInfo()
720+
ts.NoError(err)
721+
ts.False(peer2Status.VPN.VPNInterfaceEnabled)
722+
ts.NotEmpty(peer2Status.VPN.InterfaceName)
723+
ts.Equal(config.DefaultVPNNetworkSubnet, peer2Status.VPN.IPNet)
724+
725+
ts.makeFriends(peer2, peer1)
726+
727+
// Try to send traffic from peer1 (enabled) to peer2 (disabled)
728+
const packetSize = 100
729+
peer1.tun.ReferenceInboundPacketLen = packetSize
730+
peer2.tun.ClearInboundCount()
731+
732+
// Send packet
733+
p2Conf, err := peer1.api.KnownPeerConfig(peer2.app.P2p.PeerID().String())
734+
ts.NoError(err)
735+
peer2IP := p2Conf.IPAddr
736+
737+
packet := testPacketWithDest(packetSize, peer2IP)
738+
peer1.tun.Outbound <- [][]byte{packet}
739+
740+
// Wait and verify nothing received on peer2's TUN
741+
time.Sleep(1 * time.Second)
742+
ts.EqualValues(0, peer2.tun.InboundCount())
743+
}
744+
706745
func testSOCKS5Proxy(ts *TestSuite, proxyAddr string, expectSocksErr string) {
707746
// setup mock server
708747
expectedBody := strings.Repeat("test text", 10_000)

config/config.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ type (
7171
ParallelSendingStreamsCount int `json:"parallelSendingStreamsCount"`
7272
}
7373
VPNConfig struct {
74-
InterfaceName string `json:"interfaceName"`
75-
IPNet string `json:"ipNet"`
74+
DisableVPNInterface bool `json:"disableVPNInterface"`
75+
InterfaceName string `json:"interfaceName"`
76+
IPNet string `json:"ipNet"`
7677
}
7778
SOCKS5Config struct {
7879
ListenerEnabled bool `json:"listenerEnabled"`

config/network_addr.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import (
88
)
99

1010
const (
11-
defaultInterfaceName = "awl0"
11+
DefaultVPNInterfaceName = "awl0"
1212
// TODO: generate subnets if this has already taken
13-
defaultNetworkSubnet = "10.66.0.1/24"
13+
DefaultVPNNetworkSubnet = "10.66.0.1/24"
1414
)
1515

1616
func (c *Config) VPNLocalIPMask() (net.IP, net.IPMask) {

config/network_addr_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ func TestGenerateNextIpAddrExcept(t *testing.T) {
1111
// Setup base config with a VPN network
1212
conf := &Config{
1313
VPNConfig: VPNConfig{
14-
IPNet: defaultNetworkSubnet,
14+
IPNet: DefaultVPNNetworkSubnet,
1515
},
1616
KnownPeers: map[string]KnownPeer{},
1717
}

config/other.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,16 +164,16 @@ func setDefaults(conf *Config, bus awlevent.Bus) {
164164
}
165165

166166
if conf.VPNConfig.IPNet == "" {
167-
conf.VPNConfig.IPNet = defaultNetworkSubnet
167+
conf.VPNConfig.IPNet = DefaultVPNNetworkSubnet
168168
}
169169
if ip, _ := conf.VPNLocalIPMask(); ip == nil {
170-
conf.VPNConfig.IPNet = defaultNetworkSubnet
170+
conf.VPNConfig.IPNet = DefaultVPNNetworkSubnet
171171
}
172172
if conf.VPNConfig.InterfaceName == "" {
173173
if runtime.GOOS == "darwin" {
174174
conf.VPNConfig.InterfaceName = "utun"
175175
} else {
176-
conf.VPNConfig.InterfaceName = defaultInterfaceName
176+
conf.VPNConfig.InterfaceName = DefaultVPNInterfaceName
177177
}
178178
}
179179

entity/api.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,16 @@ type (
8383
Reachability string `enums:"Unknown,Public,Private"`
8484
AwlDNSAddress string
8585
IsAwlDNSSetAsSystem bool
86+
VPN VPNInfo
8687
SOCKS5 SOCKS5Info
8788
}
8889

90+
VPNInfo struct {
91+
VPNInterfaceEnabled bool
92+
InterfaceName string
93+
IPNet string
94+
}
95+
8996
SOCKS5Info struct {
9097
ListenAddress string
9198
ProxyingEnabled bool

test_suite_test.go

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,17 +96,40 @@ func (ts *TestSuite) NewTestPeer(disableLogging bool) TestPeer {
9696
return ts.newTestPeer(disableLogging, listenAddrs, nil)
9797
}
9898

99+
type ConfigModifier func(*config.Config)
100+
101+
func (ts *TestSuite) NewTestPeerWithConfig(configModifier ConfigModifier) TestPeer {
102+
listenAddrs := []multiaddr.Multiaddr{
103+
multiaddr.StringCast("/ip4/127.0.0.1/tcp/0"),
104+
multiaddr.StringCast("/ip4/127.0.0.1/udp/0/quic-v1"),
105+
}
106+
return ts.newTestPeerWithConfig(true, listenAddrs, nil, configModifier)
107+
}
108+
99109
// SOCKS5PeerConfig configures SOCKS5 settings for test peers
100110
type SOCKS5PeerConfig struct {
101111
ListenerEnabled bool
102112
ProxyingEnabled bool
103113
}
104114

105115
func (ts *TestSuite) newTestPeer(disableLogging bool, listenAddrs []multiaddr.Multiaddr, extraLibp2pOpts []libp2p.Option) TestPeer {
106-
return ts.newTestPeerWithSOCKS5(disableLogging, listenAddrs, extraLibp2pOpts, nil)
116+
return ts.newTestPeerWithConfig(disableLogging, listenAddrs, extraLibp2pOpts, nil)
107117
}
108118

109119
func (ts *TestSuite) newTestPeerWithSOCKS5(disableLogging bool, listenAddrs []multiaddr.Multiaddr, extraLibp2pOpts []libp2p.Option, socks5Conf *SOCKS5PeerConfig) TestPeer {
120+
return ts.newTestPeerWithConfig(disableLogging, listenAddrs, extraLibp2pOpts, func(c *config.Config) {
121+
if socks5Conf != nil {
122+
c.SOCKS5 = config.SOCKS5Config{
123+
ListenerEnabled: socks5Conf.ListenerEnabled,
124+
ProxyingEnabled: socks5Conf.ProxyingEnabled,
125+
ListenAddress: pickFreeAddr(ts.t),
126+
UsingPeerID: "",
127+
}
128+
}
129+
})
130+
}
131+
132+
func (ts *TestSuite) newTestPeerWithConfig(disableLogging bool, listenAddrs []multiaddr.Multiaddr, extraLibp2pOpts []libp2p.Option, configModifier ConfigModifier) TestPeer {
110133
tempDir := ts.t.TempDir()
111134
ts.t.Setenv(config.AppDataDirEnvKey, tempDir)
112135
tempConf := config.NewConfig(eventbus.NewBus())
@@ -133,15 +156,7 @@ func (ts *TestSuite) newTestPeerWithSOCKS5(disableLogging bool, listenAddrs []mu
133156
app.Conf.P2pNode.ParallelSendingStreamsCount = 1
134157
app.Conf.P2pNode.UseDedicatedConnForEachStream = false
135158

136-
// Configure SOCKS5 based on provided config or defaults
137-
if socks5Conf != nil {
138-
app.Conf.SOCKS5 = config.SOCKS5Config{
139-
ListenerEnabled: socks5Conf.ListenerEnabled,
140-
ProxyingEnabled: socks5Conf.ProxyingEnabled,
141-
ListenAddress: pickFreeAddr(ts.t),
142-
UsingPeerID: "",
143-
}
144-
} else if ts.isSimnet {
159+
if ts.isSimnet {
145160
app.Conf.SOCKS5 = config.SOCKS5Config{
146161
ListenerEnabled: false,
147162
ProxyingEnabled: false,
@@ -155,6 +170,10 @@ func (ts *TestSuite) newTestPeerWithSOCKS5(disableLogging bool, listenAddrs []mu
155170
}
156171
}
157172

173+
if configModifier != nil {
174+
configModifier(app.Conf)
175+
}
176+
158177
testTUN := NewTestTUN()
159178
err := app.Init(context.Background(), testTUN.TUN())
160179
ts.NoError(err)

0 commit comments

Comments
 (0)