mirror of
https://github.com/slackhq/nebula.git
synced 2025-11-22 08:24:25 +01:00
Switch most everything to netip in prep for ipv6 in the overlay (#1173)
This commit is contained in:
@@ -5,11 +5,11 @@ package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/slackhq/nebula"
|
||||
"github.com/slackhq/nebula/iputil"
|
||||
)
|
||||
|
||||
type edge struct {
|
||||
@@ -118,14 +118,14 @@ func renderHostmap(c *nebula.Control) (string, []*edge) {
|
||||
return r, globalLines
|
||||
}
|
||||
|
||||
func sortedHosts(hosts map[iputil.VpnIp]*nebula.HostInfo) []iputil.VpnIp {
|
||||
keys := make([]iputil.VpnIp, 0, len(hosts))
|
||||
func sortedHosts(hosts map[netip.Addr]*nebula.HostInfo) []netip.Addr {
|
||||
keys := make([]netip.Addr, 0, len(hosts))
|
||||
for key := range hosts {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
sort.SliceStable(keys, func(i, j int) bool {
|
||||
return keys[i] > keys[j]
|
||||
return keys[i].Compare(keys[j]) > 0
|
||||
})
|
||||
|
||||
return keys
|
||||
|
||||
@@ -6,12 +6,11 @@ package router
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -21,7 +20,6 @@ import (
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/slackhq/nebula"
|
||||
"github.com/slackhq/nebula/header"
|
||||
"github.com/slackhq/nebula/iputil"
|
||||
"github.com/slackhq/nebula/udp"
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
@@ -29,18 +27,18 @@ import (
|
||||
type R struct {
|
||||
// Simple map of the ip:port registered on a control to the control
|
||||
// Basically a router, right?
|
||||
controls map[string]*nebula.Control
|
||||
controls map[netip.AddrPort]*nebula.Control
|
||||
|
||||
// A map for inbound packets for a control that doesn't know about this address
|
||||
inNat map[string]*nebula.Control
|
||||
inNat map[netip.AddrPort]*nebula.Control
|
||||
|
||||
// A last used map, if an inbound packet hit the inNat map then
|
||||
// all return packets should use the same last used inbound address for the outbound sender
|
||||
// map[from address + ":" + to address] => ip:port to rewrite in the udp packet to receiver
|
||||
outNat map[string]net.UDPAddr
|
||||
outNat map[string]netip.AddrPort
|
||||
|
||||
// A map of vpn ip to the nebula control it belongs to
|
||||
vpnControls map[iputil.VpnIp]*nebula.Control
|
||||
vpnControls map[netip.Addr]*nebula.Control
|
||||
|
||||
ignoreFlows []ignoreFlow
|
||||
flow []flowEntry
|
||||
@@ -118,10 +116,10 @@ func NewR(t testing.TB, controls ...*nebula.Control) *R {
|
||||
}
|
||||
|
||||
r := &R{
|
||||
controls: make(map[string]*nebula.Control),
|
||||
vpnControls: make(map[iputil.VpnIp]*nebula.Control),
|
||||
inNat: make(map[string]*nebula.Control),
|
||||
outNat: make(map[string]net.UDPAddr),
|
||||
controls: make(map[netip.AddrPort]*nebula.Control),
|
||||
vpnControls: make(map[netip.Addr]*nebula.Control),
|
||||
inNat: make(map[netip.AddrPort]*nebula.Control),
|
||||
outNat: make(map[string]netip.AddrPort),
|
||||
flow: []flowEntry{},
|
||||
ignoreFlows: []ignoreFlow{},
|
||||
fn: filepath.Join("mermaid", fmt.Sprintf("%s.md", t.Name())),
|
||||
@@ -135,7 +133,7 @@ func NewR(t testing.TB, controls ...*nebula.Control) *R {
|
||||
for _, c := range controls {
|
||||
addr := c.GetUDPAddr()
|
||||
if _, ok := r.controls[addr]; ok {
|
||||
panic("Duplicate listen address: " + addr)
|
||||
panic("Duplicate listen address: " + addr.String())
|
||||
}
|
||||
|
||||
r.vpnControls[c.GetVpnIp()] = c
|
||||
@@ -165,13 +163,13 @@ func NewR(t testing.TB, controls ...*nebula.Control) *R {
|
||||
// It does not look at the addr attached to the instance.
|
||||
// If a route is used, this will behave like a NAT for the return path.
|
||||
// Rewriting the source ip:port to what was last sent to from the origin
|
||||
func (r *R) AddRoute(ip net.IP, port uint16, c *nebula.Control) {
|
||||
func (r *R) AddRoute(ip netip.Addr, port uint16, c *nebula.Control) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
inAddr := net.JoinHostPort(ip.String(), fmt.Sprintf("%v", port))
|
||||
inAddr := netip.AddrPortFrom(ip, port)
|
||||
if _, ok := r.inNat[inAddr]; ok {
|
||||
panic("Duplicate listen address inNat: " + inAddr)
|
||||
panic("Duplicate listen address inNat: " + inAddr.String())
|
||||
}
|
||||
r.inNat[inAddr] = c
|
||||
}
|
||||
@@ -198,7 +196,7 @@ func (r *R) renderFlow() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var participants = map[string]struct{}{}
|
||||
var participants = map[netip.AddrPort]struct{}{}
|
||||
var participantsVals []string
|
||||
|
||||
fmt.Fprintln(f, "```mermaid")
|
||||
@@ -215,7 +213,7 @@ func (r *R) renderFlow() {
|
||||
continue
|
||||
}
|
||||
participants[addr] = struct{}{}
|
||||
sanAddr := strings.Replace(addr, ":", "-", 1)
|
||||
sanAddr := strings.Replace(addr.String(), ":", "-", 1)
|
||||
participantsVals = append(participantsVals, sanAddr)
|
||||
fmt.Fprintf(
|
||||
f, " participant %s as Nebula: %s<br/>UDP: %s\n",
|
||||
@@ -252,9 +250,9 @@ func (r *R) renderFlow() {
|
||||
|
||||
fmt.Fprintf(f,
|
||||
" %s%s%s: %s(%s), index %v, counter: %v\n",
|
||||
strings.Replace(p.from.GetUDPAddr(), ":", "-", 1),
|
||||
strings.Replace(p.from.GetUDPAddr().String(), ":", "-", 1),
|
||||
line,
|
||||
strings.Replace(p.to.GetUDPAddr(), ":", "-", 1),
|
||||
strings.Replace(p.to.GetUDPAddr().String(), ":", "-", 1),
|
||||
h.TypeName(), h.SubTypeName(), h.RemoteIndex, h.MessageCounter,
|
||||
)
|
||||
}
|
||||
@@ -305,7 +303,7 @@ func (r *R) RenderHostmaps(title string, controls ...*nebula.Control) {
|
||||
func (r *R) renderHostmaps(title string) {
|
||||
c := maps.Values(r.controls)
|
||||
sort.SliceStable(c, func(i, j int) bool {
|
||||
return c[i].GetVpnIp() > c[j].GetVpnIp()
|
||||
return c[i].GetVpnIp().Compare(c[j].GetVpnIp()) > 0
|
||||
})
|
||||
|
||||
s := renderHostmaps(c...)
|
||||
@@ -420,10 +418,8 @@ func (r *R) RouteUntilTxTun(sender *nebula.Control, receiver *nebula.Control) []
|
||||
|
||||
// Nope, lets push the sender along
|
||||
case p := <-udpTx:
|
||||
outAddr := sender.GetUDPAddr()
|
||||
r.Lock()
|
||||
inAddr := net.JoinHostPort(p.ToIp.String(), fmt.Sprintf("%v", p.ToPort))
|
||||
c := r.getControl(outAddr, inAddr, p)
|
||||
c := r.getControl(sender.GetUDPAddr(), p.To, p)
|
||||
if c == nil {
|
||||
r.Unlock()
|
||||
panic("No control for udp tx")
|
||||
@@ -479,10 +475,7 @@ func (r *R) RouteForAllUntilTxTun(receiver *nebula.Control) []byte {
|
||||
} else {
|
||||
// we are a udp tx, route and continue
|
||||
p := rx.Interface().(*udp.Packet)
|
||||
outAddr := cm[x].GetUDPAddr()
|
||||
|
||||
inAddr := net.JoinHostPort(p.ToIp.String(), fmt.Sprintf("%v", p.ToPort))
|
||||
c := r.getControl(outAddr, inAddr, p)
|
||||
c := r.getControl(cm[x].GetUDPAddr(), p.To, p)
|
||||
if c == nil {
|
||||
r.Unlock()
|
||||
panic("No control for udp tx")
|
||||
@@ -509,12 +502,10 @@ func (r *R) RouteExitFunc(sender *nebula.Control, whatDo ExitFunc) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
outAddr := sender.GetUDPAddr()
|
||||
inAddr := net.JoinHostPort(p.ToIp.String(), fmt.Sprintf("%v", p.ToPort))
|
||||
receiver := r.getControl(outAddr, inAddr, p)
|
||||
receiver := r.getControl(sender.GetUDPAddr(), p.To, p)
|
||||
if receiver == nil {
|
||||
r.Unlock()
|
||||
panic("Can't route for host: " + inAddr)
|
||||
panic("Can't RouteExitFunc for host: " + p.To.String())
|
||||
}
|
||||
|
||||
e := whatDo(p, receiver)
|
||||
@@ -590,13 +581,13 @@ func (r *R) InjectUDPPacket(sender, receiver *nebula.Control, packet *udp.Packet
|
||||
// RouteForUntilAfterToAddr will route for sender and return only after it sees and sends a packet destined for toAddr
|
||||
// finish can be any of the exitType values except `keepRouting`, the default value is `routeAndExit`
|
||||
// If the router doesn't have the nebula controller for that address, we panic
|
||||
func (r *R) RouteForUntilAfterToAddr(sender *nebula.Control, toAddr *net.UDPAddr, finish ExitType) {
|
||||
func (r *R) RouteForUntilAfterToAddr(sender *nebula.Control, toAddr netip.AddrPort, finish ExitType) {
|
||||
if finish == KeepRouting {
|
||||
finish = RouteAndExit
|
||||
}
|
||||
|
||||
r.RouteExitFunc(sender, func(p *udp.Packet, r *nebula.Control) ExitType {
|
||||
if p.ToIp.Equal(toAddr.IP) && p.ToPort == uint16(toAddr.Port) {
|
||||
if p.To == toAddr {
|
||||
return finish
|
||||
}
|
||||
|
||||
@@ -630,13 +621,10 @@ func (r *R) RouteForAllExitFunc(whatDo ExitFunc) {
|
||||
r.Lock()
|
||||
|
||||
p := rx.Interface().(*udp.Packet)
|
||||
|
||||
outAddr := cm[x].GetUDPAddr()
|
||||
inAddr := net.JoinHostPort(p.ToIp.String(), fmt.Sprintf("%v", p.ToPort))
|
||||
receiver := r.getControl(outAddr, inAddr, p)
|
||||
receiver := r.getControl(cm[x].GetUDPAddr(), p.To, p)
|
||||
if receiver == nil {
|
||||
r.Unlock()
|
||||
panic("Can't route for host: " + inAddr)
|
||||
panic("Can't RouteForAllExitFunc for host: " + p.To.String())
|
||||
}
|
||||
|
||||
e := whatDo(p, receiver)
|
||||
@@ -697,12 +685,10 @@ func (r *R) FlushAll() {
|
||||
|
||||
p := rx.Interface().(*udp.Packet)
|
||||
|
||||
outAddr := cm[x].GetUDPAddr()
|
||||
inAddr := net.JoinHostPort(p.ToIp.String(), fmt.Sprintf("%v", p.ToPort))
|
||||
receiver := r.getControl(outAddr, inAddr, p)
|
||||
receiver := r.getControl(cm[x].GetUDPAddr(), p.To, p)
|
||||
if receiver == nil {
|
||||
r.Unlock()
|
||||
panic("Can't route for host: " + inAddr)
|
||||
panic("Can't FlushAll for host: " + p.To.String())
|
||||
}
|
||||
r.Unlock()
|
||||
}
|
||||
@@ -710,28 +696,14 @@ func (r *R) FlushAll() {
|
||||
|
||||
// getControl performs or seeds NAT translation and returns the control for toAddr, p from fields may change
|
||||
// This is an internal router function, the caller must hold the lock
|
||||
func (r *R) getControl(fromAddr, toAddr string, p *udp.Packet) *nebula.Control {
|
||||
if newAddr, ok := r.outNat[fromAddr+":"+toAddr]; ok {
|
||||
p.FromIp = newAddr.IP
|
||||
p.FromPort = uint16(newAddr.Port)
|
||||
func (r *R) getControl(fromAddr, toAddr netip.AddrPort, p *udp.Packet) *nebula.Control {
|
||||
if newAddr, ok := r.outNat[fromAddr.String()+":"+toAddr.String()]; ok {
|
||||
p.From = newAddr
|
||||
}
|
||||
|
||||
c, ok := r.inNat[toAddr]
|
||||
if ok {
|
||||
sHost, sPort, err := net.SplitHostPort(toAddr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
port, err := strconv.Atoi(sPort)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
r.outNat[c.GetUDPAddr()+":"+fromAddr] = net.UDPAddr{
|
||||
IP: net.ParseIP(sHost),
|
||||
Port: port,
|
||||
}
|
||||
r.outNat[c.GetUDPAddr().String()+":"+fromAddr.String()] = toAddr
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -746,8 +718,9 @@ func (r *R) formatUdpPacket(p *packet) string {
|
||||
}
|
||||
|
||||
from := "unknown"
|
||||
if c, ok := r.vpnControls[iputil.Ip2VpnIp(v4.SrcIP)]; ok {
|
||||
from = c.GetUDPAddr()
|
||||
srcAddr, _ := netip.AddrFromSlice(v4.SrcIP)
|
||||
if c, ok := r.vpnControls[srcAddr]; ok {
|
||||
from = c.GetUDPAddr().String()
|
||||
}
|
||||
|
||||
udp := packet.Layer(layers.LayerTypeUDP).(*layers.UDP)
|
||||
@@ -759,7 +732,7 @@ func (r *R) formatUdpPacket(p *packet) string {
|
||||
return fmt.Sprintf(
|
||||
" %s-->>%s: src port: %v<br/>dest port: %v<br/>data: \"%v\"\n",
|
||||
strings.Replace(from, ":", "-", 1),
|
||||
strings.Replace(p.to.GetUDPAddr(), ":", "-", 1),
|
||||
strings.Replace(p.to.GetUDPAddr().String(), ":", "-", 1),
|
||||
udp.SrcPort,
|
||||
udp.DstPort,
|
||||
string(data.Payload()),
|
||||
|
||||
Reference in New Issue
Block a user