implement nonce per-route check
This commit is contained in:
parent
6ae1fee758
commit
15897003a0
3 changed files with 42 additions and 7 deletions
|
|
@ -41,6 +41,10 @@ func (list *LuxNonceList) RotateOrFail(newNonce uint64) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (list *LuxNonceList) Flush() {
|
||||
list.nonces = make([]uint64, 0)
|
||||
}
|
||||
|
||||
func (list *LuxNonceList) Get(idx int) uint64 {
|
||||
return list.nonces[idx]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const (
|
|||
LuxPacketTypeSync = 1
|
||||
)
|
||||
|
||||
const LUX_PROTO_PACKET_HDRLEN = proto.LUX_PROTO_ID_SIZE + 2
|
||||
const LUX_PROTO_PACKET_HDRLEN = 8 + proto.LUX_PROTO_ID_SIZE + 2
|
||||
|
||||
// Target, Type are decoded from header
|
||||
// Buffer contains LuxBuffer with stripped headers
|
||||
|
|
@ -28,6 +28,7 @@ const LUX_PROTO_PACKET_HDRLEN = proto.LUX_PROTO_ID_SIZE + 2
|
|||
// Target (ID) is rather confusing. What it actually describes is
|
||||
// associated key with route.
|
||||
type LuxPacket struct {
|
||||
Nonce uint64
|
||||
Target proto.LuxID
|
||||
Type LuxPacketType
|
||||
Buffer proto.LuxBuffer
|
||||
|
|
@ -52,6 +53,13 @@ func DecryptLuxPacket(dgram LuxDatagram, key crypto.LuxKey) (LuxPacket, error) {
|
|||
decrypter.CryptBlocks(payload, dgram.Payload)
|
||||
|
||||
packet.Buffer = proto.FromSlice(payload)
|
||||
|
||||
if nonce, err := packet.Buffer.ReadUint64(); err == nil {
|
||||
packet.Nonce = nonce
|
||||
} else {
|
||||
return packet, err
|
||||
}
|
||||
|
||||
if err := packet.Target.Read(&packet.Buffer); err != nil {
|
||||
return packet, err
|
||||
|
||||
|
|
@ -99,6 +107,8 @@ func EncryptLuxPacket(packet LuxPacket, key crypto.LuxKey, target *net.UDPAddr)
|
|||
}
|
||||
|
||||
wd := proto.AllocLuxBuffer(packetLen + paddingLen)
|
||||
|
||||
wd.WriteUint64(packet.Nonce)
|
||||
key.Id.Write(&wd)
|
||||
wd.WriteUint16(uint16(packet.Type))
|
||||
wd.WriteBytes(packet.Buffer.AllBytes())
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ type LuxRoute struct {
|
|||
Key crypto.LuxKey
|
||||
Destination *net.UDPAddr
|
||||
Associated *LuxChannel
|
||||
Nonces LuxNonceList
|
||||
}
|
||||
|
||||
type LuxRouter struct {
|
||||
|
|
@ -83,6 +84,7 @@ func (r *LuxRouter) CreateOutboundRoute(id proto.LuxID, chType LuxChannelType, u
|
|||
Key: key,
|
||||
Destination: channel.Address,
|
||||
Associated: r.addOutboundChannel(channel),
|
||||
Nonces: NewLuxNonceList(),
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
@ -97,6 +99,7 @@ func (r *LuxRouter) CreateInboundChannel(chType LuxChannelType, udpAddr string)
|
|||
Key: r.thisKey,
|
||||
Destination: channel.Address,
|
||||
Associated: r.addInboundChannel(channel),
|
||||
Nonces: NewLuxNonceList(),
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
@ -216,6 +219,11 @@ func (r *LuxRouter) Recv() (LuxPacket, error) {
|
|||
var err error
|
||||
var packet LuxPacket
|
||||
|
||||
/* BUG:
|
||||
* nodes share same UUID. When updating routes by UUID, it will overwrite others' nodes routes.
|
||||
* this is current limitation of protocol
|
||||
*/
|
||||
|
||||
// first we look key from routes
|
||||
if route, ok := r.GetRoute(dgram.Target); ok {
|
||||
packet, err = DecryptLuxPacket(dgram, route.Key)
|
||||
|
|
@ -230,11 +238,11 @@ func (r *LuxRouter) Recv() (LuxPacket, error) {
|
|||
r.DeleteRoute(&route)
|
||||
return packet, errors.New("bogus packet from established route")
|
||||
/* NOTE:
|
||||
* there may be rare situation where multiple clients behind NAT/CGNAT
|
||||
* reusing same IP:Port of established route, confusing routing table.
|
||||
* This is not critical, since hosts and nodes are expected to send
|
||||
* data again after interval of time, and packet loss is expected and
|
||||
* tolerated at protocol design level.
|
||||
* there may be rare situation where multiple clients behind NAT/CGNAT
|
||||
* reusing same IP:Port of established route, confusing routing table.
|
||||
* This is not critical, since hosts and nodes are expected to send
|
||||
* data again after interval of time, and packet loss is expected and
|
||||
* tolerated at protocol design level.
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -250,16 +258,27 @@ func (r *LuxRouter) Recv() (LuxPacket, error) {
|
|||
|
||||
if bytes.Equal(packet.Target.UUID[:], key.Id.UUID[:]) {
|
||||
// key UUID and decrypted UUID matching - create OR update route and return packet
|
||||
var route *LuxRoute
|
||||
if _, idx := r.getRouteIndexByID(packet.Target); idx != -1 {
|
||||
route := &r.routes[idx]
|
||||
route = &r.routes[idx]
|
||||
route.Destination = dgram.Target
|
||||
route.Associated = dgram.Channel
|
||||
// since packet arrived from different transport, we flush nonces
|
||||
route.Nonces.Flush()
|
||||
} else {
|
||||
r.routes = append(r.routes, LuxRoute{
|
||||
Key: key,
|
||||
Destination: dgram.Target,
|
||||
Associated: dgram.Channel,
|
||||
Nonces: NewLuxNonceList(),
|
||||
})
|
||||
route = &r.routes[len(r.routes)-1]
|
||||
}
|
||||
|
||||
// rotate nonce
|
||||
if !route.Nonces.RotateOrFail(packet.Nonce) {
|
||||
// failed nonce, discard packet
|
||||
return packet, fmt.Errorf("packet failed nonce check")
|
||||
}
|
||||
|
||||
packet.ChannelType = dgram.Channel.Type
|
||||
|
|
@ -277,6 +296,7 @@ func (r *LuxRouter) Send(packet LuxPacket) error {
|
|||
return errors.New("no route to peer")
|
||||
}
|
||||
|
||||
packet.Nonce = GenerateLuxNonce()
|
||||
dgram, err := EncryptLuxPacket(packet, route.Key, route.Destination)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -289,6 +309,7 @@ func (r *LuxRouter) Send(packet LuxPacket) error {
|
|||
func (r *LuxRouter) Multicast(packet LuxPacket) error {
|
||||
for _, route := range r.routes {
|
||||
if bytes.Equal(route.Key.Id.UUID[:], packet.Target.UUID[:]) {
|
||||
packet.Nonce = GenerateLuxNonce()
|
||||
dgram, err := EncryptLuxPacket(packet, route.Key, route.Destination)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue