Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9718675

Browse files
committedAug 2, 2024··
add an automated test for UDP port forwarding
1 parent 526780d commit 9718675

File tree

4 files changed

+239
-92
lines changed

4 files changed

+239
-92
lines changed
 

‎port-forwarder/config_test.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ port_forwarding:
4646
assert.True(t, fwd_list.IsEmpty())
4747
}
4848

49-
func TestConfigWithNoProtocols2(t *testing.T) {
49+
func TestConfigWithNoProtocols_commentedProtos(t *testing.T) {
5050
l := logrus.New()
5151
c := config.NewC(l)
5252
err := c.LoadString(`
@@ -70,6 +70,22 @@ port_forwarding:
7070
assert.True(t, fwd_list.IsEmpty())
7171
}
7272

73+
func TestConfigWithNoProtocols_missing_in_out(t *testing.T) {
74+
l := logrus.New()
75+
c := config.NewC(l)
76+
err := c.LoadString(`
77+
port_forwarding:
78+
`)
79+
assert.Nil(t, err)
80+
81+
fwd_list := NewPortForwardingList()
82+
err = ParseConfig(l, c, fwd_list)
83+
assert.Nil(t, err)
84+
85+
assert.Len(t, fwd_list.configPortForwardings, 0)
86+
assert.True(t, fwd_list.IsEmpty())
87+
}
88+
7389
func TestConfigWithTcpIn(t *testing.T) {
7490
l := logrus.New()
7591
c := config.NewC(l)
+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package port_forwarder
2+
3+
import (
4+
"net"
5+
"testing"
6+
7+
"github.com/sirupsen/logrus"
8+
"github.com/slackhq/nebula/config"
9+
"github.com/slackhq/nebula/service"
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func createPortForwarderFromConfigString(l *logrus.Logger, srv *service.Service, configStr string) (*PortForwardingService, error) {
14+
c := config.NewC(l)
15+
err := c.LoadString(configStr)
16+
if err != nil {
17+
return nil, err
18+
}
19+
20+
fwd_list := NewPortForwardingList()
21+
err = ParseConfig(l, c, fwd_list)
22+
if err != nil {
23+
return nil, err
24+
}
25+
26+
pf, err := ConstructFromInitialFwdList(srv, l, &fwd_list)
27+
if err != nil {
28+
return nil, err
29+
}
30+
31+
err = pf.Activate()
32+
if err != nil {
33+
return nil, err
34+
}
35+
36+
return pf, nil
37+
}
38+
39+
func testUdpCommunication(
40+
t *testing.T,
41+
msg string,
42+
senderConn *net.UDPConn,
43+
toAddr net.Addr,
44+
receiverConn *net.UDPConn,
45+
) (senderAddr net.Addr) {
46+
data_sent := []byte(msg)
47+
var n int
48+
var err error
49+
if toAddr != nil {
50+
n, err = senderConn.WriteTo(data_sent, toAddr)
51+
} else {
52+
n, err = senderConn.Write(data_sent)
53+
}
54+
assert.Nil(t, err)
55+
assert.Equal(t, n, len(data_sent))
56+
57+
buf := make([]byte, 100)
58+
n, senderAddr, err = receiverConn.ReadFrom(buf)
59+
assert.Nil(t, err)
60+
assert.Equal(t, n, len(data_sent))
61+
assert.Equal(t, data_sent, buf[:n])
62+
return
63+
}
64+
65+
func TestUdpInOut2Clients(t *testing.T) {
66+
l := logrus.New()
67+
server, client := service.CreateTwoConnectedServices()
68+
server_pf, err := createPortForwarderFromConfigString(l, server, `
69+
port_forwarding:
70+
inbound:
71+
- listen_port: 4499
72+
dial_address: 127.0.0.1:5599
73+
protocols: [udp]
74+
`)
75+
assert.Nil(t, err)
76+
77+
assert.Len(t, server_pf.portForwardings, 1)
78+
79+
client_pf, err := createPortForwarderFromConfigString(l, client, `
80+
port_forwarding:
81+
outbound:
82+
- listen_address: 127.0.0.1:3399
83+
dial_address: 10.0.0.1:4499
84+
protocols: [udp]
85+
`)
86+
assert.Nil(t, err)
87+
88+
assert.Len(t, client_pf.portForwardings, 1)
89+
90+
client_conn_addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:3399")
91+
assert.Nil(t, err)
92+
server_conn_addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5599")
93+
assert.Nil(t, err)
94+
95+
server_listen_conn, err := net.ListenUDP("udp", server_conn_addr)
96+
assert.Nil(t, err)
97+
client1_conn, err := net.DialUDP("udp", nil, client_conn_addr)
98+
assert.Nil(t, err)
99+
client2_conn, err := net.DialUDP("udp", nil, client_conn_addr)
100+
assert.Nil(t, err)
101+
102+
client1_addr := testUdpCommunication(t, "Hello from client 1 side!",
103+
client1_conn, nil, server_listen_conn)
104+
assert.NotNil(t, client1_addr)
105+
client2_addr := testUdpCommunication(t, "Hello from client two side!",
106+
client2_conn, nil, server_listen_conn)
107+
assert.NotNil(t, client2_addr)
108+
109+
testUdpCommunication(t, "Hello from server first side!",
110+
server_listen_conn, client1_addr, client1_conn)
111+
testUdpCommunication(t, "Hello from server second side!",
112+
server_listen_conn, client2_addr, client2_conn)
113+
testUdpCommunication(t, "Hello from server third side!",
114+
server_listen_conn, client1_addr, client1_conn)
115+
116+
testUdpCommunication(t, "Hello from client two side AGAIN!",
117+
client2_conn, nil, server_listen_conn)
118+
119+
client.Close()
120+
server.Close()
121+
}

‎service/service_test.go

+1-91
Original file line numberDiff line numberDiff line change
@@ -4,103 +4,13 @@ import (
44
"bytes"
55
"context"
66
"errors"
7-
"net/netip"
87
"testing"
9-
"time"
108

11-
"dario.cat/mergo"
12-
"github.com/sirupsen/logrus"
13-
"github.com/slackhq/nebula/cert"
14-
"github.com/slackhq/nebula/config"
15-
"github.com/slackhq/nebula/e2e"
169
"golang.org/x/sync/errgroup"
17-
"gopkg.in/yaml.v2"
1810
)
1911

20-
type m map[string]interface{}
21-
22-
func newSimpleService(caCrt *cert.NebulaCertificate, caKey []byte, name string, udpIp netip.Addr, overrides m) *Service {
23-
_, _, myPrivKey, myPEM := e2e.NewTestCert(caCrt, caKey, "a", time.Now(), time.Now().Add(5*time.Minute), netip.PrefixFrom(udpIp, 24), nil, []string{})
24-
caB, err := caCrt.MarshalToPEM()
25-
if err != nil {
26-
panic(err)
27-
}
28-
29-
mc := m{
30-
"pki": m{
31-
"ca": string(caB),
32-
"cert": string(myPEM),
33-
"key": string(myPrivKey),
34-
},
35-
//"tun": m{"disabled": true},
36-
"firewall": m{
37-
"outbound": []m{{
38-
"proto": "any",
39-
"port": "any",
40-
"host": "any",
41-
}},
42-
"inbound": []m{{
43-
"proto": "any",
44-
"port": "any",
45-
"host": "any",
46-
}},
47-
},
48-
"timers": m{
49-
"pending_deletion_interval": 2,
50-
"connection_alive_interval": 2,
51-
},
52-
"handshakes": m{
53-
"try_interval": "200ms",
54-
},
55-
}
56-
57-
if overrides != nil {
58-
err = mergo.Merge(&overrides, mc, mergo.WithAppendSlice)
59-
if err != nil {
60-
panic(err)
61-
}
62-
mc = overrides
63-
}
64-
65-
cb, err := yaml.Marshal(mc)
66-
if err != nil {
67-
panic(err)
68-
}
69-
70-
var c config.C
71-
if err := c.LoadString(string(cb)); err != nil {
72-
panic(err)
73-
}
74-
75-
l := logrus.New()
76-
s, err := New(&c, l)
77-
if err != nil {
78-
panic(err)
79-
}
80-
return s
81-
}
82-
8312
func TestService(t *testing.T) {
84-
ca, _, caKey, _ := e2e.NewTestCaCert(time.Now(), time.Now().Add(10*time.Minute), nil, nil, []string{})
85-
a := newSimpleService(ca, caKey, "a", netip.MustParseAddr("10.0.0.1"), m{
86-
"static_host_map": m{},
87-
"lighthouse": m{
88-
"am_lighthouse": true,
89-
},
90-
"listen": m{
91-
"host": "0.0.0.0",
92-
"port": 4243,
93-
},
94-
})
95-
b := newSimpleService(ca, caKey, "b", netip.MustParseAddr("10.0.0.2"), m{
96-
"static_host_map": m{
97-
"10.0.0.1": []string{"localhost:4243"},
98-
},
99-
"lighthouse": m{
100-
"hosts": []string{"10.0.0.1"},
101-
"interval": 1,
102-
},
103-
})
13+
a, b := CreateTwoConnectedServices()
10414

10515
ln, err := a.Listen("tcp", ":1234")
10616
if err != nil {

‎service/service_testhelpers.go

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package service
2+
3+
import (
4+
"net/netip"
5+
"time"
6+
7+
"dario.cat/mergo"
8+
"github.com/sirupsen/logrus"
9+
"github.com/slackhq/nebula/cert"
10+
"github.com/slackhq/nebula/config"
11+
"github.com/slackhq/nebula/e2e"
12+
"gopkg.in/yaml.v2"
13+
)
14+
15+
type m map[string]interface{}
16+
17+
func newSimpleService(caCrt *cert.NebulaCertificate, caKey []byte, name string, udpIp netip.Addr, overrides m) *Service {
18+
_, _, myPrivKey, myPEM := e2e.NewTestCert(caCrt, caKey, "a", time.Now(), time.Now().Add(5*time.Minute), netip.PrefixFrom(udpIp, 24), nil, []string{})
19+
caB, err := caCrt.MarshalToPEM()
20+
if err != nil {
21+
panic(err)
22+
}
23+
24+
mc := m{
25+
"pki": m{
26+
"ca": string(caB),
27+
"cert": string(myPEM),
28+
"key": string(myPrivKey),
29+
},
30+
//"tun": m{"disabled": true},
31+
"firewall": m{
32+
"outbound": []m{{
33+
"proto": "any",
34+
"port": "any",
35+
"host": "any",
36+
}},
37+
"inbound": []m{{
38+
"proto": "any",
39+
"port": "any",
40+
"host": "any",
41+
}},
42+
},
43+
"timers": m{
44+
"pending_deletion_interval": 2,
45+
"connection_alive_interval": 2,
46+
},
47+
"handshakes": m{
48+
"try_interval": "200ms",
49+
},
50+
}
51+
52+
if overrides != nil {
53+
err = mergo.Merge(&overrides, mc, mergo.WithAppendSlice)
54+
if err != nil {
55+
panic(err)
56+
}
57+
mc = overrides
58+
}
59+
60+
cb, err := yaml.Marshal(mc)
61+
if err != nil {
62+
panic(err)
63+
}
64+
65+
var c config.C
66+
if err := c.LoadString(string(cb)); err != nil {
67+
panic(err)
68+
}
69+
70+
l := logrus.New()
71+
s, err := New(&c, l)
72+
if err != nil {
73+
panic(err)
74+
}
75+
return s
76+
}
77+
78+
func CreateTwoConnectedServices() (*Service, *Service) {
79+
ca, _, caKey, _ := e2e.NewTestCaCert(time.Now(), time.Now().Add(10*time.Minute), nil, nil, []string{})
80+
a := newSimpleService(ca, caKey, "a", netip.MustParseAddr("10.0.0.1"), m{
81+
"static_host_map": m{},
82+
"lighthouse": m{
83+
"am_lighthouse": true,
84+
},
85+
"listen": m{
86+
"host": "0.0.0.0",
87+
"port": 4243,
88+
},
89+
})
90+
b := newSimpleService(ca, caKey, "b", netip.MustParseAddr("10.0.0.2"), m{
91+
"static_host_map": m{
92+
"10.0.0.1": []string{"localhost:4243"},
93+
},
94+
"lighthouse": m{
95+
"hosts": []string{"10.0.0.1"},
96+
"interval": 1,
97+
},
98+
})
99+
return a, b
100+
}

0 commit comments

Comments
 (0)
Please sign in to comment.