From f40150a181b8ab5f4b945282dcb4e3d6fe51dba9 Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Sun, 26 Jan 2025 11:34:28 -0700 Subject: [PATCH] Implement core device tunnel proxy --- Cargo.lock | 571 +++++++++++++++++++++++++++-- Cargo.toml | 10 +- src/core_device_proxy.rs | 132 ++++++- src/lib.rs | 30 ++ src/tools/core_device_proxy_tun.rs | 124 +++++++ 5 files changed, 840 insertions(+), 27 deletions(-) create mode 100644 src/tools/core_device_proxy_tun.rs diff --git a/Cargo.lock b/Cargo.lock index 56d3147..352a0e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,6 +75,18 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-recursion" version = "1.1.1" @@ -83,9 +95,21 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.91", ] +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.4.0" @@ -104,7 +128,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -128,12 +152,51 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +[[package]] +name = "c2rust-bitfields" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "367e5d1b30f28be590b6b3868da1578361d29d9bfac516d22f497d28ed7c9055" +dependencies = [ + "c2rust-bitfields-derive", +] + +[[package]] +name = "c2rust-bitfields-derive" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a279db9c50c4024eeca1a763b6e0f033848ce74e83e47454bcf8a8a98f7b0b56" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "cc" version = "1.2.5" @@ -149,12 +212,62 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "colorchoice" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "cookie" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "cookie_store" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eac901828f88a5241ee0600950ab981148a18f2f756900ffba1b125ca6a3ef9" +dependencies = [ + "cookie", + "document-features", + "idna", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "time", + "url", +] + [[package]] name = "cpufeatures" version = "0.2.16" @@ -173,6 +286,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "crypto-common" version = "0.1.6" @@ -210,7 +329,25 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.91", +] + +[[package]] +name = "document-features" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" +dependencies = [ + "litrs", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", ] [[package]] @@ -242,6 +379,33 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + [[package]] name = "flate2" version = "1.0.35" @@ -252,6 +416,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "foreign-types" version = "0.3.2" @@ -276,6 +446,28 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -286,6 +478,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getifaddrs" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba121d81ab5ea05b0cd5858516266800bf965531a794f7ac58e3eeb804f364f" +dependencies = [ + "bitflags", + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -309,6 +512,23 @@ version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +[[package]] +name = "http" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + [[package]] name = "humantime" version = "2.1.0" @@ -430,7 +650,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.91", ] [[package]] @@ -439,6 +659,7 @@ version = "0.1.8" dependencies = [ "async-recursion", "base64", + "byteorder", "env_logger", "indexmap", "json", @@ -446,10 +667,13 @@ dependencies = [ "openssl", "plist", "serde", + "serde_json", "sha2", "thiserror", "tokio", "tokio-openssl", + "tokio-tun", + "tun-rs", "ureq", "uuid", ] @@ -486,6 +710,12 @@ dependencies = [ "serde", ] +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -510,12 +740,28 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "libloading" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + [[package]] name = "litemap" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + [[package]] name = "lock_api" version = "0.4.12" @@ -532,12 +778,31 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "mac_address" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8836fae9d0d4be2c8b4efcdd79e828a2faa058a90d005abf42f91cac5493a08e" +dependencies = [ + "nix 0.28.0", + "winapi", +] + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.8.2" @@ -558,6 +823,31 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases 0.1.1", + "libc", + "memoffset", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -602,7 +892,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.91", ] [[package]] @@ -617,6 +907,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.3" @@ -637,7 +933,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -652,6 +948,17 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.31" @@ -778,6 +1085,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "rustls-pki-types" version = "1.10.1" @@ -795,6 +1111,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + [[package]] name = "scopeguard" version = "1.2.0" @@ -818,7 +1140,19 @@ checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.91", +] + +[[package]] +name = "serde_json" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", ] [[package]] @@ -881,6 +1215,17 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.91" @@ -900,7 +1245,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.91", ] [[package]] @@ -920,7 +1265,7 @@ checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.91", ] [[package]] @@ -990,7 +1335,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.91", ] [[package]] @@ -1004,6 +1349,46 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tun" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790ebe9efc583335345a64abb56a6f36a0258aefc500990bd89cb8a9393975ba" +dependencies = [ + "libc", + "nix 0.29.0", + "thiserror", + "tokio", +] + +[[package]] +name = "tun-rs" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53141e64197ff7e758b8152615e50bb4a3b18c970738876e7906d31f242c7d6e" +dependencies = [ + "bitflags", + "blocking", + "byteorder", + "bytes", + "c2rust-bitfields", + "cfg-if", + "encoding_rs", + "getifaddrs", + "ipnet", + "libc", + "libloading", + "log", + "mac_address", + "nix 0.29.0", + "scopeguard", + "thiserror", + "tokio", + "windows-sys 0.59.0", + "winreg", + "wintun-bindings", +] + [[package]] name = "typenum" version = "1.17.0" @@ -1024,20 +1409,39 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.12.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" +checksum = "e860613aec8c8643c53fb4a3ea3bed801ac09d982b75cb5a1c579e410ef043c2" dependencies = [ "base64", + "cc", + "cookie_store", "flate2", "log", "once_cell", + "percent-encoding", "rustls", + "rustls-pemfile", "rustls-pki-types", - "url", + "serde", + "serde_json", + "ureq-proto", + "utf-8", "webpki-roots", ] +[[package]] +name = "ureq-proto" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "319fa2a136b0a13deb093ce09407b39918ecceb68abfc688d9bf9353cf840b94" +dependencies = [ + "base64", + "http", + "httparse", + "log", +] + [[package]] name = "url" version = "2.5.4" @@ -1049,6 +1453,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf16_iter" version = "1.0.5" @@ -1103,13 +1513,44 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1118,7 +1559,22 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -1127,28 +1583,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1161,30 +1635,77 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wintun-bindings" +version = "0.7.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a02981bed4592bcd271f9bfe154228ddbd2fd69e37a7d358da5d3a1251d696" +dependencies = [ + "c2rust-bitfields", + "libloading", + "log", + "thiserror", + "windows-sys 0.59.0", +] + [[package]] name = "write16" version = "1.0.0" @@ -1217,7 +1738,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.91", "synstructure", ] @@ -1238,7 +1759,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.91", "synstructure", ] @@ -1267,5 +1788,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.91", ] diff --git a/Cargo.toml b/Cargo.toml index 5174c16..8debd25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,10 @@ name = "mounter" path = "src/tools/mounter.rs" required-features = ["sha2", "ureq"] +[[bin]] +name = "core_device_proxy_tun" +path = "src/tools/core_device_proxy_tun.rs" + [dependencies] tokio = { version = "1.43", features = ["io-util", "macros", "time", "full"] } tokio-openssl = { version = "0.6" } @@ -41,10 +45,14 @@ indexmap = { version = "2.7", features = ["serde"] } uuid = { version = "1.12", features = ["serde"] } async-recursion = { version = "1.1" } base64 = { version = "0.22" } +byteorder = { version = "1.5" } +serde_json = { version = "1" } +tokio-tun = { version = "0.13" } +tun-rs = { version = "1.5", features = ["async"] } # Binary dependencies sha2 = { version = "0.10", optional = true } -ureq = { version = "2.12", optional = true } +ureq = { version = "3", optional = true } [features] bin = ["tokio/full", "sha2", "ureq"] diff --git a/src/core_device_proxy.rs b/src/core_device_proxy.rs index b93bb47..c0a2f95 100644 --- a/src/core_device_proxy.rs +++ b/src/core_device_proxy.rs @@ -2,12 +2,142 @@ use crate::{Idevice, IdeviceError}; +use byteorder::{BigEndian, WriteBytesExt}; +use serde::{Deserialize, Serialize}; +use std::io::{self, Write}; + +pub const SERVCE_NAME: &str = "com.apple.internal.devicecompute.CoreDeviceProxy"; +const DEFAULT_MTU: u32 = 16000; + +#[derive(Debug, PartialEq)] +pub struct CDTunnelPacket { + body: Vec, +} + +impl CDTunnelPacket { + const MAGIC: &'static [u8] = b"CDTunnel"; + + /// Parses a byte slice into a `CDTunnelPacket`. + pub fn parse(input: &[u8]) -> Result { + if input.len() < Self::MAGIC.len() + 2 { + return Err(IdeviceError::CdtunnelPacketTooShort); + } + + // Validate the magic bytes + if &input[0..Self::MAGIC.len()] != Self::MAGIC { + return Err(IdeviceError::CdtunnelPacketInvalidMagic); + } + + // Parse the body length + let length_offset = Self::MAGIC.len(); + let body_length = + u16::from_be_bytes([input[length_offset], input[length_offset + 1]]) as usize; + + // Validate the body length + if input.len() < length_offset + 2 + body_length { + return Err(IdeviceError::PacketSizeMismatch); + } + + // Extract the body + let body_start = length_offset + 2; + let body = input[body_start..body_start + body_length].to_vec(); + + Ok(Self { body }) + } + + /// Serializes the `CDTunnelPacket` into a byte vector. + pub fn serialize(&self) -> io::Result> { + let mut output = Vec::new(); + + // Write the magic bytes + output.write_all(Self::MAGIC)?; + + // Write the body length + output.write_u16::(self.body.len() as u16)?; + + // Write the body + output.write_all(&self.body)?; + + Ok(output) + } +} + pub struct CoreDeviceProxy { pub idevice: Idevice, + pub mtu: u32, +} + +#[derive(Serialize)] +struct HandshakeRequest { + #[serde(rename = "type")] + packet_type: String, + mtu: u32, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ClientParameters { + pub mtu: u16, + pub address: String, + pub netmask: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct HandshakeResponse { + #[serde(rename = "clientParameters")] + pub client_parameters: ClientParameters, + #[serde(rename = "serverAddress")] + pub server_address: String, + #[serde(rename = "type")] + pub response_type: String, + #[serde(rename = "serverRSDPort")] + pub server_rsd_port: u16, } impl CoreDeviceProxy { pub fn new(idevice: Idevice) -> Self { - Self { idevice } + Self { + idevice, + mtu: DEFAULT_MTU, + } + } + + pub async fn establish_tunnel(&mut self) -> Result { + let req = HandshakeRequest { + packet_type: "clientHandshakeRequest".to_string(), + mtu: DEFAULT_MTU, + }; + + let req = CDTunnelPacket::serialize(&CDTunnelPacket { + body: serde_json::to_vec(&req)?, + })?; + + self.idevice.send_raw(&req).await?; + let recv = self + .idevice + .read_raw(CDTunnelPacket::MAGIC.len() + 2) + .await?; + + if recv.len() < CDTunnelPacket::MAGIC.len() + 2 { + return Err(IdeviceError::CdtunnelPacketTooShort); + } + + let len = u16::from_be_bytes([ + recv[CDTunnelPacket::MAGIC.len()], + recv[CDTunnelPacket::MAGIC.len() + 1], + ]) as usize; + + let recv = self.idevice.read_raw(len).await?; + let res = serde_json::from_slice::(&recv)?; + + Ok(res) + } + + pub async fn send(&mut self, data: &[u8]) -> Result<(), IdeviceError> { + self.idevice.send_raw(data).await?; + Ok(()) + } + + pub async fn recv(&mut self) -> Result, IdeviceError> { + self.idevice.read_any(self.mtu).await } } diff --git a/src/lib.rs b/src/lib.rs index f819740..ca811cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,6 +72,28 @@ impl Idevice { } } + /// Reads raw bytes from the socket + async fn read_raw(&mut self, len: usize) -> Result, IdeviceError> { + if let Some(socket) = &mut self.socket { + let mut buf = vec![0; len]; + socket.read_exact(&mut buf).await?; + Ok(buf) + } else { + Err(IdeviceError::NoEstablishedConnection) + } + } + + /// Reads bytes from the socket until it doesn't + async fn read_any(&mut self, max_size: u32) -> Result, IdeviceError> { + if let Some(socket) = &mut self.socket { + let mut buf = vec![0; max_size as usize]; + let len = socket.read(&mut buf).await?; + Ok(buf[..len].to_vec()) + } else { + Err(IdeviceError::NoEstablishedConnection) + } + } + /// Read a plist from the socket async fn read_plist(&mut self) -> Result { if let Some(socket) = &mut self.socket { @@ -152,6 +174,14 @@ pub enum IdeviceError { HeartbeatTimeout, #[error("not found")] NotFound, + #[error("CDTunnel packet too short")] + CdtunnelPacketTooShort, + #[error("CDTunnel packet invalid magic")] + CdtunnelPacketInvalidMagic, + #[error("Proclaimed packet size does not match actual size")] + PacketSizeMismatch, + #[error("JSON serialization failed")] + Json(#[from] serde_json::Error), #[error("unknown error `{0}` returned from device")] UnknownErrorType(String), } diff --git a/src/tools/core_device_proxy_tun.rs b/src/tools/core_device_proxy_tun.rs new file mode 100644 index 0000000..41924da --- /dev/null +++ b/src/tools/core_device_proxy_tun.rs @@ -0,0 +1,124 @@ +// Jackson Coxson + +use idevice::{ + core_device_proxy::{self}, + lockdownd::{self, LockdowndClient}, + pairing_file::PairingFile, + Idevice, +}; +use tun_rs::AbstractDevice; + +use std::{ + net::{Ipv4Addr, SocketAddrV4}, + str::FromStr, +}; + +#[tokio::main] +async fn main() { + env_logger::init(); + let mut host = None; + let mut pairing_file = None; + + // Loop through args + let mut i = 0; + while i < std::env::args().len() { + match std::env::args().nth(i).unwrap().as_str() { + "--host" => { + host = Some(std::env::args().nth(i + 1).unwrap().to_string()); + i += 2; + } + "--pairing-file" => { + pairing_file = Some(std::env::args().nth(i + 1).unwrap().to_string()); + i += 2; + } + "-h" | "--help" => { + println!("core_device_proxy_tun - start a tunnel"); + println!("Usage:"); + println!(" core_device_proxy_tun [options]"); + println!("Options:"); + println!(" --host "); + println!(" --pairing_file "); + println!(" -h, --help"); + println!(" --about"); + println!("\n\nSet RUST_LOG to info, debug, warn, error, or trace to see more logs. Default is error."); + std::process::exit(0); + } + "--about" => { + println!("ideviceinfo - get information from the idevice. Reimplementation of libimobiledevice's binary."); + println!("Copyright (c) 2025 Jackson Coxson"); + } + _ => { + i += 1; + } + } + } + if host.is_none() { + println!("Invalid arguments! Pass the IP of the device with --host"); + return; + } + if pairing_file.is_none() { + println!("Invalid arguments! Pass the path the the pairing file with --pairing-file"); + return; + } + let ip = Ipv4Addr::from_str(host.unwrap().as_str()).unwrap(); + let socket = SocketAddrV4::new(ip, lockdownd::LOCKDOWND_PORT); + + let socket = tokio::net::TcpStream::connect(socket).await.unwrap(); + let socket = Box::new(socket); + let idevice = Idevice::new(socket, "heartbeat_client"); + + let p = PairingFile::read_from_file(pairing_file.as_ref().unwrap()).unwrap(); + + let mut lockdown_client = LockdowndClient { idevice }; + lockdown_client.start_session(&p).await.unwrap(); + + let (port, _) = lockdown_client + .start_service(core_device_proxy::SERVCE_NAME) + .await + .unwrap(); + + let socket = SocketAddrV4::new(ip, port); + let socket = tokio::net::TcpStream::connect(socket).await.unwrap(); + let socket = Box::new(socket); + let mut idevice = Idevice::new(socket, "core_device_proxy_tun"); + + let p = PairingFile::read_from_file(pairing_file.unwrap()).unwrap(); + + idevice.start_session(&p).await.unwrap(); + + let mut tun_proxy = core_device_proxy::CoreDeviceProxy::new(idevice); + let response = tun_proxy.establish_tunnel().await.unwrap(); + + let dev = tun_rs::create(&tun_rs::Configuration::default()).unwrap(); + dev.add_address_v6(response.client_parameters.address.parse().unwrap(), 32) + .unwrap(); + dev.set_mtu(response.client_parameters.mtu).unwrap(); + dev.set_network_address( + response.client_parameters.address, + response.client_parameters.netmask.parse().unwrap(), + Some(response.server_address.parse().unwrap()), + ) + .unwrap(); + + let async_dev = tun_rs::AsyncDevice::new(dev).unwrap(); + async_dev.enabled(true).unwrap(); + println!("-----------------------------"); + println!("tun device created: {:?}", async_dev.name()); + println!("server address: {}", response.server_address); + println!("rsd port: {}", response.server_rsd_port); + println!("-----------------------------"); + + let mut buf = vec![0; 1500]; + loop { + tokio::select! { + Ok(len) = async_dev.recv(&mut buf) => { + println!("tun pkt: {:?}", &buf[..len]); + tun_proxy.send(&buf[..len]).await.unwrap(); + } + Ok(res) = tun_proxy.recv() => { + println!("dev pkt: {:?}", &res); + async_dev.send(&res).await.unwrap(); + } + } + } +}