forked from slackhq/nebula
-
Notifications
You must be signed in to change notification settings - Fork 0
/
udp_tester.go
140 lines (115 loc) · 3.36 KB
/
udp_tester.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// +build e2e_testing
package nebula
import (
"fmt"
"net"
"github.com/sirupsen/logrus"
)
type UdpPacket struct {
ToIp net.IP
ToPort uint16
FromIp net.IP
FromPort uint16
Data []byte
}
func (u *UdpPacket) Copy() *UdpPacket {
n := &UdpPacket{
ToIp: make(net.IP, len(u.ToIp)),
ToPort: u.ToPort,
FromIp: make(net.IP, len(u.FromIp)),
FromPort: u.FromPort,
Data: make([]byte, len(u.Data)),
}
copy(n.ToIp, u.ToIp)
copy(n.FromIp, u.FromIp)
copy(n.Data, u.Data)
return n
}
type udpConn struct {
addr *udpAddr
rxPackets chan *UdpPacket // Packets to receive into nebula
txPackets chan *UdpPacket // Packets transmitted outside by nebula
l *logrus.Logger
}
func NewListener(l *logrus.Logger, ip string, port int, _ bool) (*udpConn, error) {
return &udpConn{
addr: &udpAddr{net.ParseIP(ip), uint16(port)},
rxPackets: make(chan *UdpPacket, 1),
txPackets: make(chan *UdpPacket, 1),
l: l,
}, nil
}
// Send will place a UdpPacket onto the receive queue for nebula to consume
// this is an encrypted packet or a handshake message in most cases
// packets were transmitted from another nebula node, you can send them with Tun.Send
func (u *udpConn) Send(packet *UdpPacket) {
h := &Header{}
if err := h.Parse(packet.Data); err != nil {
panic(err)
}
u.l.WithField("header", h).
WithField("udpAddr", fmt.Sprintf("%v:%v", packet.FromIp, packet.FromPort)).
WithField("dataLen", len(packet.Data)).
Info("UDP receiving injected packet")
u.rxPackets <- packet
}
// Get will pull a UdpPacket from the transmit queue
// nebula meant to send this message on the network, it will be encrypted
// packets were ingested from the tun side (in most cases), you can send them with Tun.Send
func (u *udpConn) Get(block bool) *UdpPacket {
if block {
return <-u.txPackets
}
select {
case p := <-u.txPackets:
return p
default:
return nil
}
}
//********************************************************************************************************************//
// Below this is boilerplate implementation to make nebula actually work
//********************************************************************************************************************//
func (u *udpConn) WriteTo(b []byte, addr *udpAddr) error {
p := &UdpPacket{
Data: make([]byte, len(b), len(b)),
FromIp: make([]byte, 16),
FromPort: u.addr.Port,
ToIp: make([]byte, 16),
ToPort: addr.Port,
}
copy(p.Data, b)
copy(p.ToIp, addr.IP.To16())
copy(p.FromIp, u.addr.IP.To16())
u.txPackets <- p
return nil
}
func (u *udpConn) ListenOut(f *Interface, q int) {
plaintext := make([]byte, mtu)
header := &Header{}
fwPacket := &FirewallPacket{}
ua := &udpAddr{IP: make([]byte, 16)}
nb := make([]byte, 12, 12)
lhh := f.lightHouse.NewRequestHandler()
conntrackCache := NewConntrackCacheTicker(f.conntrackCacheTimeout)
for {
p := <-u.rxPackets
ua.Port = p.FromPort
copy(ua.IP, p.FromIp.To16())
f.readOutsidePackets(ua, plaintext[:0], p.Data, header, fwPacket, lhh, nb, q, conntrackCache.Get(u.l))
}
}
func (u *udpConn) reloadConfig(*Config) {}
func NewUDPStatsEmitter(_ []*udpConn) func() {
// No UDP stats for non-linux
return func() {}
}
func (u *udpConn) LocalAddr() (*udpAddr, error) {
return u.addr, nil
}
func (u *udpConn) Rebind() error {
return nil
}
func hostDidRoam(addr *udpAddr, newaddr *udpAddr) bool {
return !addr.Equals(newaddr)
}