5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-26 21:11:36 +00:00

Add source addresses option and more intelligent source checking

This commit is contained in:
Neil Alexander 2018-11-05 23:59:41 +00:00
parent cfdbc481a5
commit 8c2327a2bf
No known key found for this signature in database
GPG Key ID: A02A2019A2BB0944
3 changed files with 64 additions and 12 deletions

View File

@ -12,12 +12,14 @@ import (
// allow traffic for non-Yggdrasil ranges to be routed over Yggdrasil. // allow traffic for non-Yggdrasil ranges to be routed over Yggdrasil.
type cryptokey struct { type cryptokey struct {
core *Core core *Core
enabled bool enabled bool
ipv4routes []cryptokey_route ipv4routes []cryptokey_route
ipv6routes []cryptokey_route ipv6routes []cryptokey_route
ipv4cache map[address]cryptokey_route ipv4cache map[address]cryptokey_route
ipv6cache map[address]cryptokey_route ipv6cache map[address]cryptokey_route
ipv4sources []net.IPNet
ipv6sources []net.IPNet
} }
type cryptokey_route struct { type cryptokey_route struct {
@ -31,12 +33,60 @@ func (c *cryptokey) init(core *Core) {
c.ipv6routes = make([]cryptokey_route, 0) c.ipv6routes = make([]cryptokey_route, 0)
c.ipv4cache = make(map[address]cryptokey_route, 0) c.ipv4cache = make(map[address]cryptokey_route, 0)
c.ipv6cache = make(map[address]cryptokey_route, 0) c.ipv6cache = make(map[address]cryptokey_route, 0)
c.ipv4sources = make([]net.IPNet, 0)
c.ipv6sources = make([]net.IPNet, 0)
} }
func (c *cryptokey) isEnabled() bool { func (c *cryptokey) isEnabled() bool {
return c.enabled return c.enabled
} }
func (c *cryptokey) isValidSource(addr address) bool {
ip := net.IP(addr[:])
// Does this match our node's address?
if addr == c.core.router.addr {
return true
}
// Does this match our node's subnet?
var subnet net.IPNet
copy(subnet.IP, c.core.router.subnet[:])
copy(subnet.Mask, net.CIDRMask(64, 128))
if subnet.Contains(ip) {
return true
}
// Does it match a configured CKR source?
for _, subnet := range c.ipv6sources {
if subnet.Contains(ip) {
return true
}
}
// Doesn't match any of the above
return false
}
func (c *cryptokey) addSourceSubnet(cidr string) error {
// Is the CIDR we've been given valid?
_, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
return err
}
// Check if we already have this CIDR
for _, subnet := range c.ipv6sources {
if subnet.String() == ipnet.String() {
return errors.New("Source subnet already configured")
}
}
// Add the source subnet
c.ipv6sources = append(c.ipv6sources, *ipnet)
return nil
}
func (c *cryptokey) addRoute(cidr string, dest string) error { func (c *cryptokey) addRoute(cidr string, dest string) error {
// Is the CIDR we've been given valid? // Is the CIDR we've been given valid?
ipaddr, ipnet, err := net.ParseCIDR(cidr) ipaddr, ipnet, err := net.ParseCIDR(cidr)

View File

@ -39,6 +39,7 @@ type SessionFirewall struct {
// TunnelRouting contains the crypto-key routing tables for tunneling // TunnelRouting contains the crypto-key routing tables for tunneling
type TunnelRouting struct { type TunnelRouting struct {
Enable bool `comment:"Enable or disable tunneling."` Enable bool `comment:"Enable or disable tunneling."`
IPv6Routes map[string]string `comment:"IPv6 subnets, mapped to the public keys to which they should be routed."` IPv6Routes map[string]string `comment:"IPv6 subnets, mapped to the public keys to which they should be routed."`
IPv6Sources []string `comment:"Allow source addresses in these subnets."`
} }

View File

@ -34,6 +34,7 @@ import (
type router struct { type router struct {
core *Core core *Core
addr address addr address
subnet subnet
in <-chan []byte // packets we received from the network, link to peer's "out" in <-chan []byte // packets we received from the network, link to peer's "out"
out func([]byte) // packets we're sending to the network, link to peer's "in" out func([]byte) // packets we're sending to the network, link to peer's "in"
recv chan<- []byte // place where the tun pulls received packets from recv chan<- []byte // place where the tun pulls received packets from
@ -47,6 +48,7 @@ type router struct {
func (r *router) init(core *Core) { func (r *router) init(core *Core) {
r.core = core r.core = core
r.addr = *address_addrForNodeID(&r.core.dht.nodeID) r.addr = *address_addrForNodeID(&r.core.dht.nodeID)
r.subnet = *address_subnetForNodeID(&r.core.dht.nodeID)
in := make(chan []byte, 32) // TODO something better than this... in := make(chan []byte, 32) // TODO something better than this...
p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub, &boxSharedKey{}, "(self)") p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub, &boxSharedKey{}, "(self)")
p.out = func(packet []byte) { p.out = func(packet []byte) {
@ -128,6 +130,9 @@ func (r *router) sendPacket(bs []byte) {
var snet subnet var snet subnet
copy(sourceAddr[:], bs[8:]) copy(sourceAddr[:], bs[8:])
copy(sourceSubnet[:], bs[8:]) copy(sourceSubnet[:], bs[8:])
if !r.cryptokey.isValidSource(sourceAddr) {
return
}
copy(dest[:], bs[24:]) copy(dest[:], bs[24:])
copy(snet[:], bs[24:]) copy(snet[:], bs[24:])
if !dest.isValid() && !snet.isValid() { if !dest.isValid() && !snet.isValid() {
@ -141,10 +146,6 @@ func (r *router) sendPacket(bs []byte) {
} else { } else {
return return
} }
} else {
if !sourceAddr.isValid() && !sourceSubnet.isValid() {
return
}
} }
doSearch := func(packet []byte) { doSearch := func(packet []byte) {
var nodeID, mask *NodeID var nodeID, mask *NodeID