blob: 353d291c9c46c8350a8384cbfb343669679febac [file] [log] [blame]
Serge Bazanski6b649f82021-05-24 15:09:25 +02001package kubenat
2
3import (
4 "context"
5 "flag"
6 "io/ioutil"
7 "net"
8 "os"
9 "testing"
10
11 "github.com/go-test/deep"
12)
13
14// testConntrack is the anonymized content of a production host.
15// The first entry is an appservice-irc connection from a pod to an IRC server.
16// The second connection is an UDP connection between two pods.
17// The third to last entry is not a NAT entry, but an incoming external
18// connection.
19// The fourth connection has a mangled/incomplete entry.
20const testConntrack = `
21ipv4 2 tcp 6 86384 ESTABLISHED src=10.10.26.23 dst=192.0.2.180 sport=51336 dport=6697 src=192.0.2.180 dst=185.236.240.36 sport=6697 dport=28706 [ASSURED] mark=0 zone=0 use=2
22ipv4 2 udp 17 35 src=10.10.24.162 dst=10.10.26.108 sport=49347 dport=53 src=10.10.26.108 dst=10.10.24.162 sport=53 dport=49347 [ASSURED] mark=0 zone=0 use=2
23ipv4 2 tcp 6 2 SYN_SENT src=198.51.100.67 dst=185.236.240.56 sport=51053 dport=3359 [UNREPLIED] src=185.236.240.56 dst=198.51.100.67 sport=3359 dport=51053 mark=0 zone=0 use=2
24ipv4 2 tcp 6 2
25`
26
27// TestConntrackParse exercises the conntrack parser for all entries in testConntrack.
28func TestConntrackParse(t *testing.T) {
29 // Last line is truncated and should be ignored.
30 got, err := conntrackParse([]byte(testConntrack))
31 if err != nil {
32 t.Fatalf("conntrackParse: %v", err)
33 }
34 want := []conntrackEntry{
35 {
36 "ipv4", "tcp", 86384, "ESTABLISHED",
37 map[string]string{
38 "src": "10.10.26.23", "dst": "192.0.2.180", "sport": "57640", "dport": "6697",
39 "mark": "0", "zone": "0", "use": "2",
40 },
41 map[string]string{
42 "src": "192.0.2.180", "dst": "185.236.240.36", "sport": "6697", "dport": "28706",
43 },
44 map[string]bool{
45 "ASSURED": true,
46 },
47 },
48 {
49 "ipv4", "udp", 35, "",
50 map[string]string{
51 "src": "10.10.24.162", "dst": "10.10.26.108", "sport": "49347", "dport": "53",
52 "mark": "0", "zone": "0", "use": "2",
53 },
54 map[string]string{
55 "src": "10.10.26.108", "dst": "10.10.24.162", "sport": "53", "dport": "49347",
56 },
57 map[string]bool{
58 "ASSURED": true,
59 },
60 },
61 {
62 "ipv4", "tcp", 2, "SYN_SENT",
63 map[string]string{
64 "src": "198.51.100.67", "dst": "185.236.240.56", "sport": "51053", "dport": "3359",
65 "mark": "0", "zone": "0", "use": "2",
66 },
67 map[string]string{
68 "src": "185.236.240.56", "dst": "198.51.100.67", "sport": "3359", "dport": "51053",
69 },
70 map[string]bool{
71 "UNREPLIED": true,
72 },
73 },
74 }
75 if diff := deep.Equal(want, got); diff != nil {
76 t.Error(diff)
77 }
78
79 ix := buildIndex(got)
80 if want, got := 0, len(ix.getByRequest("src", "1.2.3.4")); want != got {
81 t.Errorf("by request, src, 1.2.3.4 should have returned %d result, wanted %d", want, got)
82 }
83 if want, got := 1, len(ix.getByRequest("src", "10.10.26.23")); want != got {
84 t.Errorf("by request, src, 1.2.3.4 should have returned %d result, wanted %d", want, got)
85 }
86 if want, got := "10.10.26.23", ix.getByRequest("src", "10.10.26.23")[0].request["src"]; want != got {
87 t.Errorf("by request, wanted src %q, got %q", want, got)
88 }
89 if want, got := 3, len(ix.getByRequest("mark", "0")); want != got {
90 t.Errorf("by request, mark, 0 should have returned %d result, wanted %d", want, got)
91 }
92}
93
94// TestTranslationWorker exercises a translation worker with a
95// testConntrack-backed conntrack file.
96func TestTranslationWorker(t *testing.T) {
97 flag.Set("logtostderr", "true")
98 tmpfile, err := ioutil.TempFile("", "conntack")
99 if err != nil {
100 t.Fatal(err)
101 }
102 defer os.Remove(tmpfile.Name())
103 if _, err := tmpfile.Write([]byte(testConntrack)); err != nil {
104 t.Fatal(err)
105 }
106 r := &Resolver{
107 conntrackPath: tmpfile.Name(),
108 translationC: make(chan *translationReq),
109 }
110 ctx, ctxC := context.WithCancel(context.Background())
111 defer ctxC()
112
113 go r.runTranslationWorker(ctx)
114
115 res, err := r.translate(ctx, &Tuple4{
116 RemoteIP: net.ParseIP("192.0.2.180"),
117 RemotePort: 6697,
118 LocalIP: net.ParseIP("185.236.240.36"),
119 LocalPort: 28706,
120 })
121 if err != nil {
122 t.Fatalf("translate: %v", err)
123 }
124 if want, got := net.ParseIP("10.10.26.23"), res.localIP; !want.Equal(got) {
125 t.Errorf("local ip: wanted %v, got %v", want, got)
126 }
127 if want, got := uint16(51336), res.localPort; want != got {
128 t.Errorf("local port: wanted %d, got %d", want, got)
129 }
130}