From 929eadb651ba41bb72ba8f85a0d68c0cbad18661 Mon Sep 17 00:00:00 2001 From: Mathias Hall-Andersen Date: Sun, 1 Sep 2019 17:16:01 +0200 Subject: Outbound cryptkey routing --- Cargo.lock | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/main.rs | 3 +- src/router/device.rs | 88 ++++++++++++++++--- src/router/mod.rs | 8 ++ src/router/peer.rs | 70 +++++++++++++-- src/router/tests.rs | 173 +++++++++++++++++++++++++++++++++++++ src/router/types.rs | 29 +++++++ src/router/workers.rs | 31 ++++--- 9 files changed, 602 insertions(+), 35 deletions(-) create mode 100644 src/router/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 87c424c..d64a8f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,14 @@ dependencies = [ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arraydeque" version = "0.4.5" @@ -59,6 +67,11 @@ name = "bit-vec" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitflags" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" version = "1.1.0" @@ -290,6 +303,11 @@ dependencies = [ "wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "heck" version = "0.3.1" @@ -331,6 +349,14 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ipnetwork" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "js-sys" version = "0.3.27" @@ -372,6 +398,14 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" version = "0.4.8" @@ -516,6 +550,87 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pnet" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ipnetwork 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_base 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_datalink 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_packet 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_transport 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pnet_base" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pnet_datalink" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ipnetwork 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_base 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pnet_macros" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pnet_macros_support" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pnet_base 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pnet_packet" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_base 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_macros 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_macros_support 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pnet_sys" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pnet_transport" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_base 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_packet 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "poly1305" version = "0.2.0" @@ -732,6 +847,18 @@ name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "regex" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex-syntax" version = "0.6.11" @@ -764,6 +891,11 @@ name = "rustc-demangle" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc_version" version = "0.2.3" @@ -815,6 +947,11 @@ name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "serde" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "slab" version = "0.4.2" @@ -889,6 +1026,51 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syntex" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syntex_errors" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syntex_pos" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syntex_syntax" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tempfile" version = "3.1.0" @@ -902,6 +1084,23 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "term" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio" version = "0.1.22" @@ -1086,6 +1285,11 @@ name = "unicode-segmentation" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-xid" version = "0.1.0" @@ -1101,6 +1305,11 @@ name = "untrusted" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "utf8-ranges" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "version_check" version = "0.1.5" @@ -1250,6 +1459,7 @@ dependencies = [ "hjul 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", "proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.16.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1306,6 +1516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aead 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "529ae27769da55d955d190396e67896f49b440aff94a5b2f50900e091d168b77" +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum arraydeque 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0ffd3d69bd89910509a5d31d1f1353f38ccffdd116dd0099bbd6627f7bd8ad8" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" @@ -1313,6 +1524,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" "checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" +"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330" "checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" @@ -1342,17 +1554,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fc344b02d3868feb131e8b5fe2b9b0a1cc42942679af493061fc13b853243872" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hjul 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea9ffb9dc3e645a3fd2820b8c2f3e1c27f48586678f95cf287d75af018eba577" "checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum ipnetwork 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3d862c86f7867f19b693ec86765e0252d82e53d4240b9b629815675a0714ad1" "checksum js-sys 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)" = "1efc4f2a556c58e79c5500912e221dd826bec64ff4aabd8ce71ccef6da02d7d4" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" @@ -1369,6 +1584,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum pnet 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63d693c84430248366146e3181ff9d330243464fa9e6146c372b2f3eb2e2d8e7" +"checksum pnet_base 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4df28acf2fcc77436dd2b91a9a0c2bb617f9ca5f2acefee1a4135058b9f9801f" +"checksum pnet_datalink 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b34f8ca857599d05b6b082e9baff8d27c54cb9c26568cf3c0993a5755816966" +"checksum pnet_macros 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f16d1fa7fd0edebc36055587b8b5af8a109bbc29a55fb484a37e2029b971a7" +"checksum pnet_macros_support 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84684f2cddefc37a06f2fe2ca4dcc3457fc3b282734b5246507d8ee75d2780ae" +"checksum pnet_packet 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a6cdcdaddc5174f18286298842a4e31cd3cc018933d42af51434b1fa07dcbe" +"checksum pnet_sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "682b2eca84cc440bce8336813f78eb6d3cb0fed89fe0e87ae22acfca8363f176" +"checksum pnet_transport 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5faa55dcf725487a699adcff88dfea8f17ea34fa2640528866d9acbb4e3a104f" "checksum poly1305 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb59dfc6d8dd49677e39bf8fdf4c62235a8d84dbe2ef2913e139d3f62bb65f70" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" @@ -1393,10 +1616,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467" "checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum ring 0.16.7 (registry+https://github.com/rust-lang/crates.io-index)" = "796ae8317a07b04dffb1983bdc7045ccd02f741f0b411704f07fd35dbf99f757" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rusty-fork 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd93264e10c577503e926bd1430193eeb5d21b059148910082245309b424fae" "checksum salsa20-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fd325cb25b420aab2c035b5b76966d9f91b88fb54084ce6c0cd072a1ae5cda" @@ -1404,6 +1629,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" @@ -1415,7 +1641,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +"checksum syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a30b08a6b383a22e5f6edc127d169670d48f905bb00ca79a00ea3e442ebe317" +"checksum syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04c48f32867b6114449155b2a82114b86d4b09e1bddb21c47ff104ab9172b646" +"checksum syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd49988e52451813c61fecbe9abb5cfd4e1b7bb6cdbb980a6fbcbab859171a6" +"checksum syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7628a0506e8f9666fdabb5f265d0059b059edac9a3f810bda077abb5d826bd8d" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" @@ -1432,9 +1664,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum treebitmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bf423939ac9ccf4083788879b883a7149176586f9cf8b0fb1fd88b66ad692b5" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" +"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" +"checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum wait-timeout 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" "checksum wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd5442abcac6525a045cc8c795aedb60da7a2e5e89c7bf18a0d5357849bb23c7" diff --git a/Cargo.toml b/Cargo.toml index 0689086..05b44b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,3 +36,4 @@ features = ["nightly"] [dev-dependencies] proptest = "0.9.4" +pnet = "^0.22" diff --git a/src/main.rs b/src/main.rs index 6d1d2e1..8d92048 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,10 +10,9 @@ use hjul::*; use std::error::Error; use std::fmt; use std::net::SocketAddr; -use std::sync::Arc; use std::time::Duration; -use types::{Bind, KeyPair, Tun}; +use types::{Bind, Tun}; #[derive(Debug)] enum TunError {} diff --git a/src/router/device.rs b/src/router/device.rs index f04cf97..4fb0334 100644 --- a/src/router/device.rs +++ b/src/router/device.rs @@ -1,6 +1,7 @@ +use std::cmp; use std::collections::HashMap; use std::net::{Ipv4Addr, Ipv6Addr}; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::{Arc, Weak}; use std::thread; use std::time::Instant; @@ -14,10 +15,21 @@ use super::super::types::{Bind, KeyPair, Tun}; use super::anti_replay::AntiReplay; use super::peer; use super::peer::{Peer, PeerInner}; +use super::SIZE_MESSAGE_PREFIX; -use super::types::{Callback, Callbacks, KeyCallback, Opaque, PhantomCallbacks}; +use super::types::{Callback, Callbacks, KeyCallback, Opaque, PhantomCallbacks, RouterError}; use super::workers::{worker_parallel, JobParallel}; +// minimum sizes for IP headers +const SIZE_IP4_HEADER: usize = 16; +const SIZE_IP6_HEADER: usize = 36; + +const VERSION_IP4: u8 = 4; +const VERSION_IP6: u8 = 6; + +const OFFSET_IP4_DST: usize = 16; +const OFFSET_IP6_DST: usize = 24; + pub struct DeviceInner { // IO & timer generics pub tun: T, @@ -27,9 +39,9 @@ pub struct DeviceInner { pub call_need_key: C::CallbackKey, // threading and workers - pub running: AtomicBool, // workers running? - pub parked: AtomicBool, // any workers parked? - pub injector: Injector, // parallel enc/dec task injector + pub running: AtomicBool, // workers running? + pub parked: AtomicBool, // any workers parked? + pub injector: Injector>, // parallel enc/dec task injector // routing pub recv: spin::RwLock>>, // receiver id -> decryption state @@ -38,11 +50,10 @@ pub struct DeviceInner { } pub struct EncryptionState { - pub key: [u8; 32], // encryption key - pub id: u32, // sender id - pub nonce: u64, // next available nonce - pub death: Instant, // time when the key no longer can be used for encryption - // (birth + reject-after-time - keepalive-timeout - rekey-timeout) + pub key: [u8; 32], // encryption key + pub id: u32, // receiver id + pub nonce: u64, // next available nonce + pub death: Instant, // (birth + reject-after-time - keepalive-timeout - rekey-timeout) } pub struct DecryptionState { @@ -144,8 +155,61 @@ impl Device { /// /// - pt_msg: IP packet to cryptkey route /// - pub fn send(&self, pt_msg: &mut [u8]) { - unimplemented!(); + pub fn send(&self, msg: Vec) -> Result<(), RouterError> { + // ensure that the type field access is within bounds + if msg.len() < cmp::min(SIZE_IP4_HEADER, SIZE_IP6_HEADER) + SIZE_MESSAGE_PREFIX { + return Err(RouterError::MalformedIPHeader); + } + + // ignore header prefix (for in-place transport message construction) + let packet = &msg[SIZE_MESSAGE_PREFIX..]; + + // lookup peer based on IP packet destination address + let peer = match packet[0] >> 4 { + VERSION_IP4 => { + if msg.len() >= SIZE_IP4_HEADER { + // extract IPv4 destination address + let mut dst = [0u8; 4]; + dst.copy_from_slice(&packet[OFFSET_IP4_DST..OFFSET_IP4_DST + 4]); + let dst = Ipv4Addr::from(dst); + + // lookup peer (project unto and clone "value" field) + self.0 + .ipv4 + .read() + .longest_match(dst) + .and_then(|(_, _, p)| p.upgrade()) + .ok_or(RouterError::NoCryptKeyRoute) + } else { + Err(RouterError::MalformedIPHeader) + } + } + VERSION_IP6 => { + if msg.len() >= SIZE_IP6_HEADER { + // extract IPv6 destination address + let mut dst = [0u8; 16]; + dst.copy_from_slice(&packet[OFFSET_IP6_DST..OFFSET_IP6_DST + 16]); + let dst = Ipv6Addr::from(dst); + + // lookup peer (project unto and clone "value" field) + self.0 + .ipv6 + .read() + .longest_match(dst) + .and_then(|(_, _, p)| p.upgrade()) + .ok_or(RouterError::NoCryptKeyRoute) + } else { + Err(RouterError::MalformedIPHeader) + } + } + _ => Err(RouterError::MalformedIPHeader), + }?; + + // schedule for encryption and transmission to peer + if let Some(job) = peer.send_job(msg) { + self.0.injector.push((peer.clone(), job)); + } + Ok(()) } /// Receive an encrypted transport message diff --git a/src/router/mod.rs b/src/router/mod.rs index c1ecf1c..0e4bce1 100644 --- a/src/router/mod.rs +++ b/src/router/mod.rs @@ -5,5 +5,13 @@ mod peer; mod types; mod workers; +#[cfg(test)] +mod tests; + +use messages::TransportHeader; +use std::mem; + +pub const SIZE_MESSAGE_PREFIX: usize = mem::size_of::(); + pub use device::Device; pub use peer::Peer; diff --git a/src/router/peer.rs b/src/router/peer.rs index e21e69c..d755fa5 100644 --- a/src/router/peer.rs +++ b/src/router/peer.rs @@ -1,3 +1,4 @@ +use std::mem; use std::net::{IpAddr, SocketAddr}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::mpsc::{sync_channel, SyncSender}; @@ -7,18 +8,23 @@ use std::thread; use spin; use arraydeque::{ArrayDeque, Wrapping}; +use zerocopy::{AsBytes, LayoutVerified}; use treebitmap::address::Address; use treebitmap::IpLookupTable; use super::super::constants::*; -use super::super::types::{KeyPair, Tun, Bind}; +use super::super::types::{Bind, KeyPair, Tun}; use super::anti_replay::AntiReplay; use super::device::DecryptionState; use super::device::DeviceInner; use super::device::EncryptionState; -use super::workers::{worker_inbound, worker_outbound, JobInbound, JobOutbound}; +use super::messages::TransportHeader; + +use super::workers::{worker_inbound, worker_outbound}; +use super::workers::{JobBuffer, JobInbound, JobInner, JobOutbound}; +use super::workers::{Operation, Status}; use super::types::Callbacks; @@ -40,16 +46,14 @@ pub struct PeerInner { pub queue_outbound: SyncSender, pub queue_inbound: SyncSender>, pub staged_packets: spin::Mutex; MAX_STAGED_PACKETS], Wrapping>>, // packets awaiting handshake - pub rx_bytes: AtomicU64, // received bytes - pub tx_bytes: AtomicU64, // transmitted bytes + pub rx_bytes: AtomicU64, // received bytes + pub tx_bytes: AtomicU64, // transmitted bytes pub keys: spin::Mutex, // key-wheel pub ekey: spin::Mutex>, // encryption state pub endpoint: spin::Mutex>>, } -pub struct Peer( - Arc>, -); +pub struct Peer(Arc>); fn treebit_list( peer: &Arc>, @@ -212,6 +216,51 @@ impl PeerInner { // rotate key-wheel } + + pub fn send_job(&self, mut msg: Vec) -> Option { + debug_assert!(msg.len() >= mem::size_of::()); + + // parse / cast + let (header, _) = LayoutVerified::new_from_prefix(&mut msg[..]).unwrap(); + let mut header: LayoutVerified<&mut [u8], TransportHeader> = header; + + // check if has key + let key = match self.ekey.lock().as_mut() { + None => { + // add to staged packets (create no job) + (self.device.call_need_key)(&self.opaque); + self.staged_packets.lock().push_back(msg); + return None; + } + Some(mut state) => { + // allocate nonce + state.nonce += 1; + if state.nonce >= REJECT_AFTER_MESSAGES { + state.nonce -= 1; + return None; + } + + // set transport message fields + header.f_counter.set(state.nonce); + header.f_receiver.set(state.id); + state.key + } + }; + + // create job + let job = Arc::new(spin::Mutex::new(JobInner { + msg, + key, + status: Status::Waiting, + op: Operation::Encryption, + })); + + // add job to in-order queue and return to device for inclusion in worker pool + match self.queue_outbound.try_send(job.clone()) { + Ok(_) => Some(job), + Err(_) => None, + } + } } impl Peer { @@ -332,5 +381,10 @@ impl Peer { res } - pub fn send(&self, msg: Vec) {} + pub fn remove_subnets(&self) { + treebit_remove(self, &self.0.device.ipv4); + treebit_remove(self, &self.0.device.ipv6); + } + + fn send(&self, msg: Vec) {} } diff --git a/src/router/tests.rs b/src/router/tests.rs new file mode 100644 index 0000000..07851a8 --- /dev/null +++ b/src/router/tests.rs @@ -0,0 +1,173 @@ +use std::error::Error; +use std::fmt; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; + +use pnet::packet::ipv4::MutableIpv4Packet; +use pnet::packet::ipv6::MutableIpv6Packet; + +use super::super::types::{Bind, Tun}; +use super::{Device, Peer, SIZE_MESSAGE_PREFIX}; + +#[derive(Debug)] +enum TunError {} + +impl Error for TunError { + fn description(&self) -> &str { + "Generic Tun Error" + } + + fn source(&self) -> Option<&(dyn Error + 'static)> { + None + } +} + +impl fmt::Display for TunError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Not Possible") + } +} + +struct TunTest {} + +impl Tun for TunTest { + type Error = TunError; + + fn mtu(&self) -> usize { + 1500 + } + + fn read(&self, buf: &mut [u8], offset: usize) -> Result { + Ok(0) + } + + fn write(&self, src: &[u8]) -> Result<(), Self::Error> { + Ok(()) + } +} + +struct BindTest {} + +impl Bind for BindTest { + type Error = BindError; + type Endpoint = SocketAddr; + + fn new() -> BindTest { + BindTest {} + } + + fn set_port(&self, port: u16) -> Result<(), Self::Error> { + Ok(()) + } + + fn get_port(&self) -> Option { + None + } + + fn recv(&self, buf: &mut [u8]) -> Result<(usize, Self::Endpoint), Self::Error> { + Ok((0, "127.0.0.1:8080".parse().unwrap())) + } + + fn send(&self, buf: &[u8], dst: &Self::Endpoint) -> Result<(), Self::Error> { + Ok(()) + } +} + +#[derive(Debug)] +enum BindError {} + +impl Error for BindError { + fn description(&self) -> &str { + "Generic Bind Error" + } + + fn source(&self) -> Option<&(dyn Error + 'static)> { + None + } +} + +impl fmt::Display for BindError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Not Possible") + } +} + +#[test] +fn test_outbound() { + let opaque = Arc::new(AtomicBool::new(false)); + + // create device (with Opaque = ()) + let workers = 4; + let router = Device::new( + workers, + TunTest {}, + BindTest {}, + |t: &Arc, data: bool, sent: bool| {}, + |t: &Arc, data: bool, sent: bool| {}, + |t: &Arc| t.store(true, Ordering::SeqCst), + ); + + // create peer + let peer = router.new_peer(opaque.clone()); + let tests = vec![ + ("192.168.1.0", 24, "192.168.1.20", true), + ("172.133.133.133", 32, "172.133.133.133", true), + ("172.133.133.133", 32, "172.133.133.132", false), + ( + "2001:db8::ff00:42:0000", + 112, + "2001:db8::ff00:42:3242", + true, + ), + ( + "2001:db8::ff00:42:8000", + 113, + "2001:db8::ff00:42:0660", + false, + ), + ( + "2001:db8::ff00:42:8000", + 113, + "2001:db8::ff00:42:ffff", + true, + ), + ]; + + for (mask, len, ip, okay) in &tests { + opaque.store(false, Ordering::SeqCst); + + let mask: IpAddr = mask.parse().unwrap(); + + // map subnet to peer + peer.add_subnet(mask, *len); + + // create "IP packet" + let mut msg = Vec::::new(); + msg.resize(SIZE_MESSAGE_PREFIX + 1024, 0); + if mask.is_ipv4() { + let mut packet = MutableIpv4Packet::new(&mut msg[SIZE_MESSAGE_PREFIX..]).unwrap(); + packet.set_destination(ip.parse().unwrap()); + packet.set_version(4); + } else { + let mut packet = MutableIpv6Packet::new(&mut msg[SIZE_MESSAGE_PREFIX..]).unwrap(); + packet.set_destination(ip.parse().unwrap()); + packet.set_version(6); + } + + // cryptkey route the IP packet + let res = router.send(msg); + if *okay { + // cryptkey routing succeeded + assert!(res.is_ok()); + + // and a key should have been requested + assert!(opaque.load(Ordering::Acquire)); + } else { + assert!(res.is_err()); + } + + // clear subnets for next test + peer.remove_subnets(); + } +} diff --git a/src/router/types.rs b/src/router/types.rs index 82dcd09..5077686 100644 --- a/src/router/types.rs +++ b/src/router/types.rs @@ -1,4 +1,6 @@ +use std::fmt; use std::marker::PhantomData; +use std::error::Error; pub trait Opaque: Send + Sync + 'static {} @@ -49,3 +51,30 @@ impl, S: Callback, K: KeyCallback> Callbacks type CallbackSend = S; type CallbackKey = K; } + + + +#[derive(Debug)] +pub enum RouterError { + NoCryptKeyRoute, + MalformedIPHeader, +} + +impl fmt::Display for RouterError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + RouterError::NoCryptKeyRoute => write!(f, "No cryptkey route configured for subnet"), + RouterError::MalformedIPHeader => write!(f, "IP header is malformed") + } + } +} + +impl Error for RouterError { + fn description(&self) -> &str { + "Generic Handshake Error" + } + + fn source(&self) -> Option<&(dyn Error + 'static)> { + None + } +} \ No newline at end of file diff --git a/src/router/workers.rs b/src/router/workers.rs index c4a9f18..1af2cae 100644 --- a/src/router/workers.rs +++ b/src/router/workers.rs @@ -9,7 +9,7 @@ use spin; use crossbeam_deque::{Injector, Steal, Stealer, Worker}; use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305}; -use zerocopy::{AsBytes, ByteSlice, ByteSliceMut, FromBytes, LayoutVerified, Unaligned}; +use zerocopy::{AsBytes, LayoutVerified}; use super::device::DecryptionState; use super::device::DeviceInner; @@ -17,7 +17,7 @@ use super::messages::TransportHeader; use super::peer::PeerInner; use super::types::Callbacks; -use super::super::types::{Tun, Bind}; +use super::super::types::{Bind, Tun}; #[derive(PartialEq, Debug)] pub enum Operation { @@ -26,21 +26,21 @@ pub enum Operation { } #[derive(PartialEq, Debug)] -enum Status { +pub enum Status { Fault, // unsealing failed Done, // job valid and complete Waiting, // job awaiting completion } pub struct JobInner { - msg: Vec, // message buffer (nonce and receiver id set) - key: [u8; 32], // chacha20poly1305 key - status: Status, // state of the job - op: Operation, // should be buffer be encrypted / decrypted? + pub msg: Vec, // message buffer (nonce and receiver id set) + pub key: [u8; 32], // chacha20poly1305 key + pub status: Status, // state of the job + pub op: Operation, // should be buffer be encrypted / decrypted? } pub type JobBuffer = Arc>; -pub type JobParallel = (Arc>, JobBuffer); +pub type JobParallel = (Arc>, JobBuffer); pub type JobInbound = (Weak>, JobBuffer); pub type JobOutbound = JobBuffer; @@ -207,13 +207,13 @@ pub fn worker_outbound( pub fn worker_parallel( device: Arc>, - local: Worker, // local job queue (local to thread) - stealers: Vec>, // stealers (from other threads) + local: Worker>, // local job queue (local to thread) + stealers: Vec>>, // stealers (from other threads) ) { while device.running.load(Ordering::SeqCst) { match find_task(&local, &device.injector, &stealers) { Some(job) => { - let (handle, buf) = job; + let (peer, buf) = job; // take ownership of the job buffer and complete it { @@ -260,8 +260,13 @@ pub fn worker_parallel( } } - // ensure consumer is unparked - handle.thread().unpark(); + // ensure consumer is unparked (TODO: better looking + wrap in atomic?) + peer.thread_outbound + .lock() + .as_ref() + .unwrap() + .thread() + .unpark(); } None => { device.parked.store(true, Ordering::Release); -- cgit v1.2.3-59-g8ed1b