encrypt traffic with pre-shared key
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
// TODO: slice bounds checking
|
||||
// TODO: authentication
|
||||
// TODO: encryption
|
||||
// TODO: somehow persist IPs
|
||||
// TODO: handle multiple peers behind one NAT
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"log"
|
||||
"net"
|
||||
@@ -21,10 +21,14 @@ type Peer struct {
|
||||
InternalIP string
|
||||
}
|
||||
|
||||
// TODO: replace with key exchange between peers
|
||||
const PSK = "rj5FvWB0n342C6UGrAS0gI3GX5ya+lDmC7/XmgFHF+s="
|
||||
|
||||
var (
|
||||
peers = map[string]*Peer{}
|
||||
peersMutex sync.Mutex
|
||||
conn *net.UDPConn
|
||||
pskKey []byte
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -32,6 +36,12 @@ func main() {
|
||||
panic("root permissions needed")
|
||||
}
|
||||
|
||||
var err error
|
||||
pskKey, err = base64.StdEncoding.DecodeString(PSK)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
receivePackets()
|
||||
}
|
||||
|
||||
@@ -59,25 +69,22 @@ func receivePackets() {
|
||||
continue
|
||||
}
|
||||
|
||||
go receivePacket(buffer[:n], addr)
|
||||
go handleReq(buffer[:n], addr)
|
||||
}
|
||||
}
|
||||
|
||||
func receivePacket(pkt []byte, addr *net.UDPAddr) {
|
||||
if len(pkt) < 4 {
|
||||
func handleReq(req []byte, addr *net.UDPAddr) {
|
||||
if len(req) < 4 {
|
||||
log.Println("packet too short")
|
||||
return
|
||||
}
|
||||
version := binary.LittleEndian.Uint16(pkt[0:])
|
||||
version := binary.LittleEndian.Uint16(req[0:])
|
||||
if version != shared.PROTO_VERSION {
|
||||
log.Println("mismatched packet version")
|
||||
return
|
||||
}
|
||||
|
||||
pktType := binary.LittleEndian.Uint16(pkt[2:])
|
||||
|
||||
// idk if it needs to lock the mutex
|
||||
peer := peers[addr.IP.String()]
|
||||
pktType := binary.LittleEndian.Uint16(req[2:])
|
||||
|
||||
switch pktType {
|
||||
case shared.REQ_REGISTER:
|
||||
@@ -98,15 +105,33 @@ func receivePacket(pkt []byte, addr *net.UDPAddr) {
|
||||
resp := shared.BuildPkt(shared.RESP_REGISTER, net.ParseIP(internalIP))
|
||||
sendTo(addr, resp)
|
||||
case shared.REQ_DATA:
|
||||
frame := pkt[4:]
|
||||
etherType := binary.BigEndian.Uint16(frame[12:14])
|
||||
payload := frame[14:]
|
||||
peersMutex.Lock()
|
||||
peer := peers[addr.IP.String()]
|
||||
peersMutex.Unlock()
|
||||
if peer == nil {
|
||||
log.Println("data from unregistered peer:", addr.String())
|
||||
return
|
||||
}
|
||||
|
||||
pkt, err := shared.DecryptSym(pskKey, req[4:])
|
||||
if err != nil {
|
||||
log.Printf("failed to decrypt packet from %s: %s", peer.RealAddr, err)
|
||||
return
|
||||
}
|
||||
|
||||
etherType := binary.BigEndian.Uint16(pkt[12:14])
|
||||
payload := pkt[14:]
|
||||
|
||||
switch etherType {
|
||||
case 0x86dd: // IPv6
|
||||
rawDestIP := payload[24:40]
|
||||
destIP := net.IP(rawDestIP).String()
|
||||
resp := shared.BuildPkt(shared.RESP_DATA, frame)
|
||||
|
||||
encryptedPkt, err := shared.EncryptSym(pskKey, pkt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
resp := shared.BuildPkt(shared.RESP_DATA, encryptedPkt)
|
||||
|
||||
if rawDestIP[0] == 0xff { // multicast
|
||||
log.Println(peer.InternalIP + " -> " + destIP + " (*)")
|
||||
|
||||
Reference in New Issue
Block a user