mirror of
https://github.com/slackhq/nebula.git
synced 2024-11-10 17:24:37 +08:00
6e0ae4f9a3
* firewall: add option to send REJECT replies This change allows you to configure the firewall to send REJECT packets when a packet is denied. firewall: # Action to take when a packet is not allowed by the firewall rules. # Can be one of: # `drop` (default): silently drop the packet. # `reject`: send a reject reply. # - For TCP, this will be a RST "Connection Reset" packet. # - For other protocols, this will be an ICMP port unreachable packet. outbound_action: drop inbound_action: drop These packets are only sent to established tunnels, and only on the overlay network (currently IPv4 only). $ ping -c1 192.168.100.3 PING 192.168.100.3 (192.168.100.3) 56(84) bytes of data. From 192.168.100.3 icmp_seq=2 Destination Port Unreachable --- 192.168.100.3 ping statistics --- 2 packets transmitted, 0 received, +1 errors, 100% packet loss, time 31ms $ nc -nzv 192.168.100.3 22 (UNKNOWN) [192.168.100.3] 22 (?) : Connection refused This change also modifies the smoke test to capture tcpdump pcaps from both the inside and outside to inspect what is going on over the wire. It also now does TCP and UDP packet tests using the Nmap version of ncat. * calculate seq and ack the same was as the kernel The logic a bit confusing, so we copy it straight from how the kernel does iptables `--reject-with tcp-reset`: - https://github.com/torvalds/linux/blob/v5.19/net/ipv4/netfilter/nf_reject_ipv4.c#L193-L221 * cleanup
132 lines
2.6 KiB
Go
132 lines
2.6 KiB
Go
package overlay
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/rcrowley/go-metrics"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/slackhq/nebula/iputil"
|
|
)
|
|
|
|
type disabledTun struct {
|
|
read chan []byte
|
|
cidr *net.IPNet
|
|
|
|
// Track these metrics since we don't have the tun device to do it for us
|
|
tx metrics.Counter
|
|
rx metrics.Counter
|
|
l *logrus.Logger
|
|
}
|
|
|
|
func newDisabledTun(cidr *net.IPNet, queueLen int, metricsEnabled bool, l *logrus.Logger) *disabledTun {
|
|
tun := &disabledTun{
|
|
cidr: cidr,
|
|
read: make(chan []byte, queueLen),
|
|
l: l,
|
|
}
|
|
|
|
if metricsEnabled {
|
|
tun.tx = metrics.GetOrRegisterCounter("messages.tx.message", nil)
|
|
tun.rx = metrics.GetOrRegisterCounter("messages.rx.message", nil)
|
|
} else {
|
|
tun.tx = &metrics.NilCounter{}
|
|
tun.rx = &metrics.NilCounter{}
|
|
}
|
|
|
|
return tun
|
|
}
|
|
|
|
func (*disabledTun) Activate() error {
|
|
return nil
|
|
}
|
|
|
|
func (*disabledTun) RouteFor(iputil.VpnIp) iputil.VpnIp {
|
|
return 0
|
|
}
|
|
|
|
func (t *disabledTun) Cidr() *net.IPNet {
|
|
return t.cidr
|
|
}
|
|
|
|
func (*disabledTun) Name() string {
|
|
return "disabled"
|
|
}
|
|
|
|
func (t *disabledTun) Read(b []byte) (int, error) {
|
|
r, ok := <-t.read
|
|
if !ok {
|
|
return 0, io.EOF
|
|
}
|
|
|
|
if len(r) > len(b) {
|
|
return 0, fmt.Errorf("packet larger than mtu: %d > %d bytes", len(r), len(b))
|
|
}
|
|
|
|
t.tx.Inc(1)
|
|
if t.l.Level >= logrus.DebugLevel {
|
|
t.l.WithField("raw", prettyPacket(r)).Debugf("Write payload")
|
|
}
|
|
|
|
return copy(b, r), nil
|
|
}
|
|
|
|
func (t *disabledTun) handleICMPEchoRequest(b []byte) bool {
|
|
out := make([]byte, len(b))
|
|
out = iputil.CreateICMPEchoResponse(b, out)
|
|
if out == nil {
|
|
return false
|
|
}
|
|
|
|
// attempt to write it, but don't block
|
|
select {
|
|
case t.read <- out:
|
|
default:
|
|
t.l.Debugf("tun_disabled: dropped ICMP Echo Reply response")
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func (t *disabledTun) Write(b []byte) (int, error) {
|
|
t.rx.Inc(1)
|
|
|
|
// Check for ICMP Echo Request before spending time doing the full parsing
|
|
if t.handleICMPEchoRequest(b) {
|
|
if t.l.Level >= logrus.DebugLevel {
|
|
t.l.WithField("raw", prettyPacket(b)).Debugf("Disabled tun responded to ICMP Echo Request")
|
|
}
|
|
} else if t.l.Level >= logrus.DebugLevel {
|
|
t.l.WithField("raw", prettyPacket(b)).Debugf("Disabled tun received unexpected payload")
|
|
}
|
|
return len(b), nil
|
|
}
|
|
|
|
func (t *disabledTun) NewMultiQueueReader() (io.ReadWriteCloser, error) {
|
|
return t, nil
|
|
}
|
|
|
|
func (t *disabledTun) Close() error {
|
|
if t.read != nil {
|
|
close(t.read)
|
|
t.read = nil
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type prettyPacket []byte
|
|
|
|
func (p prettyPacket) String() string {
|
|
var s strings.Builder
|
|
|
|
for i, b := range p {
|
|
if i > 0 && i%8 == 0 {
|
|
s.WriteString(" ")
|
|
}
|
|
s.WriteString(fmt.Sprintf("%02x ", b))
|
|
}
|
|
|
|
return s.String()
|
|
}
|