Merge pull request #62 from Arceliar/udpclose

UDP Close packet, admin removePeer
This commit is contained in:
Neil Alexander 2018-03-17 20:43:57 +00:00 committed by GitHub
commit 0f8aab7609
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 95 additions and 3 deletions

View File

@ -3,6 +3,7 @@ package yggdrasil
import "net" import "net"
import "os" import "os"
import "bytes" import "bytes"
import "errors"
import "fmt" import "fmt"
import "sort" import "sort"
import "strings" import "strings"
@ -63,6 +64,13 @@ func (a *admin) init(c *Core, listenaddr string) {
*out = []byte("Failed to add peer: " + saddr[0] + "\n") *out = []byte("Failed to add peer: " + saddr[0] + "\n")
} }
}) })
a.addHandler("removePeer", []string{"<peer>"}, func(out *[]byte, saddr ...string) {
if a.removePeer(saddr[0]) == nil {
*out = []byte("Removing peer: " + saddr[0] + "\n")
} else {
*out = []byte("Failed to remove peer: " + saddr[0] + "\n")
}
})
a.addHandler("setTunTap", []string{"<ifname|auto|none>", "[<tun|tap>]", "[<mtu>]"}, func(out *[]byte, ifparams ...string) { a.addHandler("setTunTap", []string{"<ifname|auto|none>", "[<tun|tap>]", "[<mtu>]"}, func(out *[]byte, ifparams ...string) {
// Set sane defaults // Set sane defaults
iftapmode := false iftapmode := false
@ -216,6 +224,30 @@ func (a *admin) addPeer(p string) error {
return nil return nil
} }
func (a *admin) removePeer(p string) error {
pAddr := p
if p[:4] == "tcp:" || p[:4] == "udp:" {
pAddr = p[4:]
}
switch {
case len(p) >= 4 && p[:4] == "udp:":
// Connect to peer over UDP
udpAddr, err := net.ResolveUDPAddr("udp", pAddr)
if err != nil {
return err
}
var addr connAddr
addr.fromUDPAddr(udpAddr)
a.core.udp.sendClose(addr)
return nil
case len(p) >= 4 && p[:4] == "tcp:":
default:
// Connect to peer over TCP
return errors.New("Removing TCP peer not yet supported")
}
return nil
}
func (a *admin) startTunWithMTU(ifname string, iftapmode bool, ifmtu int) error { func (a *admin) startTunWithMTU(ifname string, iftapmode bool, ifmtu int) error {
// Close the TUN first if open // Close the TUN first if open
_ = a.core.tun.close() _ = a.core.tun.close()

View File

@ -51,6 +51,7 @@ type connInfo struct {
peer *peer peer *peer
linkIn chan []byte linkIn chan []byte
keysIn chan *udpKeys keysIn chan *udpKeys
closeIn chan *udpKeys
timeout int // count of how many heartbeats have been missed timeout int // count of how many heartbeats have been missed
in func([]byte) in func([]byte)
out chan []byte out chan []byte
@ -87,9 +88,23 @@ func (iface *udpInterface) sendKeys(addr connAddr) {
iface.sock.WriteToUDP(msg, udpAddr) iface.sock.WriteToUDP(msg, udpAddr)
} }
func (iface *udpInterface) sendClose(addr connAddr) {
udpAddr := addr.toUDPAddr()
msg := []byte{}
msg = udp_encode(msg, 0, 1, 0, nil)
msg = append(msg, iface.core.boxPub[:]...)
msg = append(msg, iface.core.sigPub[:]...)
iface.sock.WriteToUDP(msg, udpAddr)
}
func udp_isKeys(msg []byte) bool { func udp_isKeys(msg []byte) bool {
keyLen := 3 + boxPubKeyLen + sigPubKeyLen keyLen := 3 + boxPubKeyLen + sigPubKeyLen
return len(msg) == keyLen && msg[0] == 0x00 return len(msg) == keyLen && msg[0] == 0x00 && msg[1] == 0x00
}
func udp_isClose(msg []byte) bool {
keyLen := 3 + boxPubKeyLen + sigPubKeyLen
return len(msg) == keyLen && msg[0] == 0x00 && msg[1] == 0x01
} }
func (iface *udpInterface) startConn(info *connInfo) { func (iface *udpInterface) startConn(info *connInfo) {
@ -111,11 +126,21 @@ func (iface *udpInterface) startConn(info *connInfo) {
iface.core.peers.mutex.Unlock() iface.core.peers.mutex.Unlock()
close(info.linkIn) close(info.linkIn)
close(info.keysIn) close(info.keysIn)
close(info.closeIn)
close(info.out) close(info.out)
iface.sendClose(info.addr)
iface.core.log.Println("Removing peer:", info.name) iface.core.log.Println("Removing peer:", info.name)
}() }()
for { for {
select { select {
case ks := <-info.closeIn:
{
if ks.box == info.peer.box && ks.sig == info.peer.sig {
// TODO? secure this somehow
// Maybe add a signature and sequence number (timestamp) to close and keys?
return
}
}
case ks := <-info.keysIn: case ks := <-info.keysIn:
{ {
// FIXME? need signatures/sequence-numbers or something // FIXME? need signatures/sequence-numbers or something
@ -136,6 +161,37 @@ func (iface *udpInterface) startConn(info *connInfo) {
} }
} }
func (iface *udpInterface) handleClose(msg []byte, addr connAddr) {
//defer util_putBytes(msg)
var ks udpKeys
_, _, _, bs := udp_decode(msg)
switch {
case !wire_chop_slice(ks.box[:], &bs):
return
case !wire_chop_slice(ks.sig[:], &bs):
return
}
if ks.box == iface.core.boxPub {
return
}
if ks.sig == iface.core.sigPub {
return
}
iface.mutex.RLock()
conn, isIn := iface.conns[addr]
iface.mutex.RUnlock()
if !isIn {
return
}
func() {
defer func() { recover() }()
select {
case conn.closeIn <- &ks:
default:
}
}()
}
func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) { func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
//defer util_putBytes(msg) //defer util_putBytes(msg)
var ks udpKeys var ks udpKeys
@ -167,6 +223,7 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
peer: iface.core.peers.newPeer(&ks.box, &ks.sig), peer: iface.core.peers.newPeer(&ks.box, &ks.sig),
linkIn: make(chan []byte, 1), linkIn: make(chan []byte, 1),
keysIn: make(chan *udpKeys, 1), keysIn: make(chan *udpKeys, 1),
closeIn: make(chan *udpKeys, 1),
out: make(chan []byte, 32), out: make(chan []byte, 32),
chunkSize: 576 - 60 - 8 - 3, // max safe - max ip - udp header - chunk overhead chunkSize: 576 - 60 - 8 - 3, // max safe - max ip - udp header - chunk overhead
} }
@ -277,7 +334,8 @@ func (iface *udpInterface) reader() {
msg := bs[:n] msg := bs[:n]
var addr connAddr var addr connAddr
addr.fromUDPAddr(udpAddr) addr.fromUDPAddr(udpAddr)
if udp_isKeys(msg) { switch {
case udp_isKeys(msg):
var them address var them address
copy(them[:], udpAddr.IP.To16()) copy(them[:], udpAddr.IP.To16())
if them.isValid() { if them.isValid() {
@ -288,7 +346,9 @@ func (iface *udpInterface) reader() {
continue continue
} }
iface.handleKeys(msg, addr) iface.handleKeys(msg, addr)
} else { case udp_isClose(msg):
iface.handleClose(msg, addr)
default:
iface.handlePacket(msg, addr) iface.handlePacket(msg, addr)
} }
} }