mirror of
https://github.com/slackhq/nebula.git
synced 2025-04-14 17:38:30 +00:00
Provide hooks for custom message packet handlers
This commit augments the Control API by providing new methods to inject message packets destined peer nodes, and/or to intercept message packets of a custom message subtype that are received from peer nodes.
This commit is contained in:
parent
fa034a6d83
commit
ae3ee42469
3 changed files with 51 additions and 3 deletions
41
control.go
41
control.go
|
@ -1,6 +1,8 @@
|
|||
package nebula
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
@ -8,6 +10,7 @@ import (
|
|||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/slackhq/nebula/cert"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
// Every interaction here needs to take extra care to copy memory and not return or use arguments "as is" when touching
|
||||
|
@ -167,3 +170,41 @@ func copyHostInfo(h *HostInfo) ControlHostInfo {
|
|||
|
||||
return chi
|
||||
}
|
||||
|
||||
// Hook provides the ability to hook into the network path for a particular
|
||||
// message sub type. Any received message of that subtype that is allowed by
|
||||
// the firewall will be written to the provided write func instead of the
|
||||
// inside interface.
|
||||
// TODO: make this an io.Writer
|
||||
func (c *Control) Hook(t NebulaMessageSubType, w func([]byte) error) error {
|
||||
if t == 0 {
|
||||
return fmt.Errorf("non-default message subtype must be specified")
|
||||
}
|
||||
if _, ok := c.f.handlers[Version][message][t]; ok {
|
||||
return fmt.Errorf("message subtype %d already hooked", t)
|
||||
}
|
||||
|
||||
c.f.handlers[Version][message][t] = c.f.newHook(w)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Send provides the ability to send arbitrary message packets to peer nodes.
|
||||
// The provided payload will be encapsulated in an IPv4 packet from the
|
||||
// node IP to the provided destination nebula IP. Any protocol handling
|
||||
// above layer 3 (IP) must be managed by the caller.
|
||||
func (c *Control) Send(ip uint32, t NebulaMessageSubType, payload []byte) {
|
||||
hostinfo := c.f.getOrHandshake(ip)
|
||||
ci := hostinfo.ConnectionState
|
||||
|
||||
length := ipv4.HeaderLen + len(payload)
|
||||
packet := make([]byte, length)
|
||||
packet[0] = 0x45
|
||||
binary.BigEndian.PutUint16(packet[2:4], uint16(length))
|
||||
binary.BigEndian.PutUint32(packet[12:16], ip2int(c.f.inside.CidrNet().IP.To4()))
|
||||
binary.BigEndian.PutUint32(packet[16:20], ip)
|
||||
copy(packet[ipv4.HeaderLen:], payload)
|
||||
|
||||
nb := make([]byte, 12)
|
||||
out := make([]byte, mtu)
|
||||
c.f.sendNoMetrics(message, t, ci, hostinfo, hostinfo.remote, packet, nb, out)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
package nebula
|
||||
|
||||
func (f *Interface) newHook(w func([]byte) error) InsideHandler {
|
||||
fn := func(hostInfo *HostInfo, ci *ConnectionState, addr *udpAddr, header *Header, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
|
||||
f.decryptTo(w, hostInfo, header.MessageCounter, out, packet, fwPacket, nb)
|
||||
}
|
||||
return f.encrypted(fn)
|
||||
}
|
||||
|
||||
func (f *Interface) encrypted(h InsideHandler) InsideHandler {
|
||||
return func(hostInfo *HostInfo, ci *ConnectionState, addr *udpAddr, header *Header, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
|
||||
if !f.handleEncrypted(ci, addr, header) {
|
||||
|
@ -21,7 +28,7 @@ func (f *Interface) rxMetrics(h InsideHandler) InsideHandler {
|
|||
}
|
||||
|
||||
func (f *Interface) handleMessagePacket(hostInfo *HostInfo, ci *ConnectionState, addr *udpAddr, header *Header, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
|
||||
f.decryptToTun(hostInfo, header.MessageCounter, out, packet, fwPacket, nb)
|
||||
f.decryptTo(f.inside.WriteRaw, hostInfo, header.MessageCounter, out, packet, fwPacket, nb)
|
||||
}
|
||||
|
||||
func (f *Interface) handleLighthousePacket(hostInfo *HostInfo, ci *ConnectionState, addr *udpAddr, header *Header, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
|
||||
|
|
|
@ -175,7 +175,7 @@ func (f *Interface) decrypt(hostinfo *HostInfo, mc uint64, out []byte, packet []
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (f *Interface) decryptToTun(hostinfo *HostInfo, messageCounter uint64, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
|
||||
func (f *Interface) decryptTo(write func([]byte) error, hostinfo *HostInfo, messageCounter uint64, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
|
||||
var err error
|
||||
|
||||
out, err = hostinfo.ConnectionState.dKey.DecryptDanger(out, packet[:HeaderLen], packet[HeaderLen:], messageCounter, nb)
|
||||
|
@ -210,7 +210,7 @@ func (f *Interface) decryptToTun(hostinfo *HostInfo, messageCounter uint64, out
|
|||
}
|
||||
|
||||
f.connectionManager.In(hostinfo.hostId)
|
||||
err = f.inside.WriteRaw(out)
|
||||
err = write(out)
|
||||
if err != nil {
|
||||
l.WithError(err).Error("Failed to write to tun")
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue