Skip to content

Commit 955b037

Browse files
committed
Limit interfaces listened on by NGINX, fixes #54
1 parent b71b15a commit 955b037

File tree

5 files changed

+123
-7
lines changed

5 files changed

+123
-7
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,14 @@ tilt up
115115

116116
First start of wormhole will be really slow - it compiles the go code inside the container. Subsequent starts will be faster, as the go build cache is preserved in PVC.
117117

118+
The development environment deploys a server, two clients and a mock service, that you can use to test the tunnels.
119+
120+
```
121+
kubectl annotate --overwrite svc --namespace nginx nginx wormhole.glothriel.github.com/exposed=yes
122+
```
123+
124+
The additional services should be immediately created. Please note, that all three workloads are deployed on the same (and by extension are monitoring the same services for annotations), so the nginx will be exposed 4 times - client1 to server, client2 to server, server to client1 and server to client2.
125+
118126
### Integration tests
119127

120128
```

pkg/cmd/client.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,15 @@ var joinCommand *cli.Command = &cli.Command{
5050
"local",
5151
nginx.NewDefaultReloader(),
5252
nginx.NewRangePortAllocator(20000, 25000),
53+
nginx.NewOnlyWireguardListener(),
5354
))
5455

5556
remoteNginxExposer := nginx.NewNginxExposer(
5657
c.String(nginxExposerConfdPathFlag.Name),
5758
"remote",
5859
nginx.NewDefaultReloader(),
5960
nginx.NewRangePortAllocator(25001, 30000),
61+
nginx.NewAllAcceptWireguardListener(),
6062
)
6163
var effectiveExposer listeners.Exposer = remoteNginxExposer
6264

pkg/cmd/server.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,15 @@ var listenCommand *cli.Command = &cli.Command{
8181
"local",
8282
nginx.NewDefaultReloader(),
8383
nginx.NewRangePortAllocator(20000, 25000),
84+
nginx.NewOnlyWireguardListener(),
8485
))
8586

8687
remoteNginxExposer := nginx.NewNginxExposer(
8788
c.String(nginxExposerConfdPathFlag.Name),
8889
"remote",
8990
nginx.NewDefaultReloader(),
9091
nginx.NewRangePortAllocator(25001, 30000),
92+
nginx.NewAllAcceptWireguardListener(),
9193
)
9294
var effectiveExposer listeners.Exposer = remoteNginxExposer
9395

pkg/nginx/exposer.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ import (
1515

1616
// Exposer is an Exposer implementation that uses NGINX as a proxy server
1717
type Exposer struct {
18-
prefix string
19-
path string
20-
fs afero.Fs
18+
prefix string
19+
path string
20+
fs afero.Fs
21+
listener Listener
2122

2223
reloader Reloader
2324
ports PortAllocator
@@ -35,17 +36,24 @@ func (n *Exposer) Add(app peers.App) (peers.App, error) {
3536
File: nginxConfigPath(n.prefix, app),
3637
App: app,
3738
}
38-
39+
listen := ""
40+
listenAddrs, listenerErr := n.listener.Addrs(port)
41+
if listenerErr != nil || len(listenAddrs) == 0 {
42+
logrus.Errorf("Could not get listener addresses: %v", listenerErr)
43+
}
44+
for _, addr := range listenAddrs {
45+
listen += fmt.Sprintf(" listen %s;\n", addr)
46+
}
3947
if writeErr := afero.WriteFile(n.fs, path.Join(n.path, server.File), []byte(fmt.Sprintf(`
4048
# [%s] %s
4149
server {
42-
listen %d;
50+
%s
4351
proxy_pass %s;
4452
}
4553
`,
4654
server.App.Peer,
4755
server.App.Name,
48-
server.ListenPort,
56+
listen,
4957
server.ProxyPass,
5058
)), 0644); writeErr != nil {
5159
logrus.Errorf("Could not write NGINX config file: %v", writeErr)
@@ -117,7 +125,9 @@ func (n *Exposer) WithdrawAll() error {
117125
}
118126

119127
// NewNginxExposer creates a new NGINX exposer
120-
func NewNginxExposer(path, confPrefix string, reloader Reloader, allocator PortAllocator) listeners.Exposer {
128+
func NewNginxExposer(
129+
path, confPrefix string, reloader Reloader, allocator PortAllocator, listener Listener,
130+
) listeners.Exposer {
121131
fs := afero.NewOsFs()
122132
cg := &Exposer{
123133
path: path,
@@ -126,6 +136,7 @@ func NewNginxExposer(path, confPrefix string, reloader Reloader, allocator PortA
126136

127137
reloader: reloader,
128138
ports: allocator,
139+
listener: listener,
129140
}
130141
createErr := fs.MkdirAll(path, 0755)
131142
if createErr != nil && createErr != afero.ErrDestinationExists {

pkg/nginx/listener.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package nginx
2+
3+
import (
4+
"fmt"
5+
"net"
6+
"strings"
7+
)
8+
9+
// Listener is an interface for NGINX listeners
10+
type Listener interface {
11+
// Addrs returns a list of addresses that the listener is listening on
12+
Addrs(portNumber int) ([]string, error)
13+
}
14+
15+
type portOnlyListener struct {
16+
}
17+
18+
// Addrs implements Listener
19+
func (p *portOnlyListener) Addrs(portNumber int) ([]string, error) {
20+
return []string{fmt.Sprintf("%d", portNumber)}, nil
21+
}
22+
23+
// NewPortOnlyListener creates a new Listener that listens on a single port
24+
func NewPortOnlyListener() Listener {
25+
return &portOnlyListener{}
26+
}
27+
28+
type wg0FilteringListener struct {
29+
includeWg0 bool
30+
}
31+
32+
// Addrs implements Listener
33+
func (a *wg0FilteringListener) Addrs(portNumber int) ([]string, error) {
34+
interfaces, interfacesErr := net.Interfaces()
35+
if interfacesErr != nil {
36+
return []string{}, interfacesErr
37+
}
38+
39+
var allAddrs []string
40+
41+
for _, iface := range interfaces {
42+
if iface.Name == "wg0" && !a.includeWg0 {
43+
continue
44+
}
45+
if iface.Name != "wg0" && a.includeWg0 {
46+
continue
47+
}
48+
49+
addrs, err := iface.Addrs()
50+
if err != nil {
51+
fmt.Println("Error retrieving addresses for interface:", iface.Name, err)
52+
continue
53+
}
54+
55+
for _, addr := range addrs {
56+
switch v := addr.(type) {
57+
// Ignore ipv6
58+
case *net.IPNet:
59+
if strings.Contains(v.IP.String(), ":") {
60+
continue
61+
} else {
62+
allAddrs = append(allAddrs, formatIP(v.IP, portNumber))
63+
}
64+
65+
case *net.IPAddr:
66+
if strings.Contains(v.IP.String(), ":") {
67+
continue
68+
} else {
69+
allAddrs = append(allAddrs, formatIP(v.IP, portNumber))
70+
}
71+
}
72+
}
73+
}
74+
return allAddrs, nil
75+
}
76+
77+
func formatIP(ip fmt.Stringer, portNumber int) string {
78+
return fmt.Sprintf("%s:%d", ip.String(), portNumber)
79+
}
80+
81+
// NewAllAcceptWireguardListener creates a new Listener that listens on all interfaces accept wg0
82+
func NewAllAcceptWireguardListener() Listener {
83+
return &wg0FilteringListener{
84+
includeWg0: false,
85+
}
86+
}
87+
88+
// NewOnlyWireguardListener creates a new Listener that listens on all interfaces
89+
func NewOnlyWireguardListener() Listener {
90+
return &wg0FilteringListener{
91+
includeWg0: true,
92+
}
93+
}

0 commit comments

Comments
 (0)