close to finish a tun/smoltcp
This commit is contained in:
Generated
+501
-2
@@ -22,6 +22,12 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android_log-sys"
|
name = "android_log-sys"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@@ -114,6 +120,17 @@ version = "4.7.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
|
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-trait"
|
||||||
|
version = "0.1.89"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atomic-waker"
|
name = "atomic-waker"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
@@ -186,6 +203,16 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.2.56"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
|
||||||
|
dependencies = [
|
||||||
|
"find-msvc-tools",
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cesu8"
|
name = "cesu8"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -333,6 +360,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "critical-section"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.21"
|
version = "0.8.21"
|
||||||
@@ -376,6 +409,12 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "data-encoding"
|
||||||
|
version = "2.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "defmt"
|
name = "defmt"
|
||||||
version = "0.3.100"
|
version = "0.3.100"
|
||||||
@@ -428,6 +467,29 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "displaydoc"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enum-as-inner"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "env_logger"
|
name = "env_logger"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
@@ -487,12 +549,33 @@ version = "0.2.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "find-msvc-tools"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foldhash"
|
name = "foldhash"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foldhash"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "form_urlencoded"
|
||||||
|
version = "1.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
|
||||||
|
dependencies = [
|
||||||
|
"percent-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.32"
|
version = "0.3.32"
|
||||||
@@ -612,6 +695,18 @@ dependencies = [
|
|||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi",
|
||||||
|
"wasip2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@@ -641,7 +736,7 @@ version = "0.15.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"foldhash",
|
"foldhash 0.1.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -649,6 +744,11 @@ name = "hashbrown"
|
|||||||
version = "0.16.1"
|
version = "0.16.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||||
|
dependencies = [
|
||||||
|
"allocator-api2",
|
||||||
|
"equivalent",
|
||||||
|
"foldhash 0.2.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heapless"
|
name = "heapless"
|
||||||
@@ -672,6 +772,31 @@ version = "0.4.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hickory-proto"
|
||||||
|
version = "0.25.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"cfg-if",
|
||||||
|
"data-encoding",
|
||||||
|
"enum-as-inner",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-io",
|
||||||
|
"futures-util",
|
||||||
|
"idna",
|
||||||
|
"ipnet",
|
||||||
|
"once_cell",
|
||||||
|
"rand 0.9.2",
|
||||||
|
"ring",
|
||||||
|
"thiserror 2.0.18",
|
||||||
|
"tinyvec",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hkdf"
|
name = "hkdf"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
@@ -690,12 +815,114 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_collections"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"potential_utf",
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_locale_core"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"litemap",
|
||||||
|
"tinystr",
|
||||||
|
"writeable",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_normalizer"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
|
||||||
|
dependencies = [
|
||||||
|
"icu_collections",
|
||||||
|
"icu_normalizer_data",
|
||||||
|
"icu_properties",
|
||||||
|
"icu_provider",
|
||||||
|
"smallvec",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_normalizer_data"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_properties"
|
||||||
|
version = "2.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec"
|
||||||
|
dependencies = [
|
||||||
|
"icu_collections",
|
||||||
|
"icu_locale_core",
|
||||||
|
"icu_properties_data",
|
||||||
|
"icu_provider",
|
||||||
|
"zerotrie",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_properties_data"
|
||||||
|
version = "2.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_provider"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"icu_locale_core",
|
||||||
|
"writeable",
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
"zerotrie",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "id-arena"
|
name = "id-arena"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "idna"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
|
||||||
|
dependencies = [
|
||||||
|
"idna_adapter",
|
||||||
|
"smallvec",
|
||||||
|
"utf8_iter",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "idna_adapter"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
|
||||||
|
dependencies = [
|
||||||
|
"icu_normalizer",
|
||||||
|
"icu_properties",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.13.0"
|
version = "2.13.0"
|
||||||
@@ -785,6 +1012,12 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "litemap"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
@@ -800,6 +1033,15 @@ version = "0.4.29"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lru"
|
||||||
|
version = "0.16.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown 0.16.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "managed"
|
name = "managed"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@@ -838,9 +1080,11 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"android_logger",
|
"android_logger",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"hickory-proto",
|
||||||
"jni",
|
"jni",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
|
"lru",
|
||||||
"netrunner-common",
|
"netrunner-common",
|
||||||
"smoltcp",
|
"smoltcp",
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
@@ -860,7 +1104,7 @@ dependencies = [
|
|||||||
"hex",
|
"hex",
|
||||||
"hkdf",
|
"hkdf",
|
||||||
"hmac",
|
"hmac",
|
||||||
"rand",
|
"rand 0.10.0",
|
||||||
"sha2",
|
"sha2",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -903,6 +1147,10 @@ name = "once_cell"
|
|||||||
version = "1.21.3"
|
version = "1.21.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
dependencies = [
|
||||||
|
"critical-section",
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell_polyfill"
|
name = "once_cell_polyfill"
|
||||||
@@ -945,6 +1193,12 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "percent-encoding"
|
||||||
|
version = "2.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@@ -973,6 +1227,30 @@ dependencies = [
|
|||||||
"universal-hash",
|
"universal-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "potential_utf"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
|
||||||
|
dependencies = [
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prettyplease"
|
name = "prettyplease"
|
||||||
version = "0.2.37"
|
version = "0.2.37"
|
||||||
@@ -1029,6 +1307,16 @@ version = "5.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||||
|
dependencies = [
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core 0.9.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@@ -1040,6 +1328,16 @@ dependencies = [
|
|||||||
"rand_core 0.10.0",
|
"rand_core 0.10.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.9.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.6.4"
|
version = "0.6.4"
|
||||||
@@ -1049,6 +1347,15 @@ dependencies = [
|
|||||||
"getrandom 0.2.17",
|
"getrandom 0.2.17",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.3.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@@ -1093,6 +1400,20 @@ version = "0.8.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c"
|
checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ring"
|
||||||
|
version = "0.17.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"getrandom 0.2.17",
|
||||||
|
"libc",
|
||||||
|
"untrusted",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@@ -1186,6 +1507,12 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.8"
|
version = "1.4.8"
|
||||||
@@ -1262,6 +1589,17 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "synstructure"
|
||||||
|
version = "0.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.69"
|
version = "1.0.69"
|
||||||
@@ -1311,6 +1649,31 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinystr"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec_macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.49.0"
|
version = "1.49.0"
|
||||||
@@ -1462,6 +1825,30 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "untrusted"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "url"
|
||||||
|
version = "2.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed"
|
||||||
|
dependencies = [
|
||||||
|
"form_urlencoded",
|
||||||
|
"idna",
|
||||||
|
"percent-encoding",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8_iter"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -1572,6 +1959,15 @@ dependencies = [
|
|||||||
"windows-targets 0.42.2",
|
"windows-targets 0.42.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.59.0"
|
version = "0.59.0"
|
||||||
@@ -1899,6 +2295,12 @@ dependencies = [
|
|||||||
"wasmparser",
|
"wasmparser",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "writeable"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x25519-dalek"
|
name = "x25519-dalek"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
@@ -1911,6 +2313,70 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yoke"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
|
||||||
|
dependencies = [
|
||||||
|
"stable_deref_trait",
|
||||||
|
"yoke-derive",
|
||||||
|
"zerofrom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yoke-derive"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"synstructure",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.8.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.8.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerofrom"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
|
||||||
|
dependencies = [
|
||||||
|
"zerofrom-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerofrom-derive"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"synstructure",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeroize"
|
name = "zeroize"
|
||||||
version = "1.8.2"
|
version = "1.8.2"
|
||||||
@@ -1931,6 +2397,39 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerotrie"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerovec"
|
||||||
|
version = "0.11.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
|
||||||
|
dependencies = [
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
"zerovec-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerovec-derive"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zmij"
|
name = "zmij"
|
||||||
version = "1.0.21"
|
version = "1.0.21"
|
||||||
|
|||||||
@@ -34,3 +34,5 @@ lazy_static = "1.4.0"
|
|||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
|
hickory-proto = "0.25.2"
|
||||||
|
lru = "0.16.3"
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
use hickory_proto::op::{Message, MessageType, ResponseCode};
|
||||||
|
use hickory_proto::rr::{RData, Record};
|
||||||
|
|
||||||
|
use crate::connections::ip_store::FakeIpStore;
|
||||||
|
|
||||||
|
pub fn handle_dns_query(data: &[u8], store: &mut FakeIpStore) -> Option<Vec<u8>> {
|
||||||
|
// 1. Парсим входящий запрос
|
||||||
|
let request = Message::from_vec(data).ok()?;
|
||||||
|
|
||||||
|
// 2. Берем первый вопрос (обычно запрос только один)
|
||||||
|
let query = request.queries().first()?;
|
||||||
|
let name = query.name().to_string().trim_end_matches('.').to_string();
|
||||||
|
|
||||||
|
// 3. Получаем Fake IP
|
||||||
|
let fake_ip = store.get_or_assign(&name);
|
||||||
|
|
||||||
|
// 4. Формируем ответ
|
||||||
|
let mut response = Message::new();
|
||||||
|
response
|
||||||
|
.set_id(request.id())
|
||||||
|
.set_message_type(MessageType::Response)
|
||||||
|
.set_response_code(ResponseCode::NoError)
|
||||||
|
.add_query(query.clone());
|
||||||
|
|
||||||
|
// Создаем запись A (IPv4)
|
||||||
|
let record = Record::from_rdata(
|
||||||
|
query.name().clone(),
|
||||||
|
1, // TTL = 1 сек
|
||||||
|
RData::A(fake_ip.into()),
|
||||||
|
);
|
||||||
|
response.add_answer(record);
|
||||||
|
|
||||||
|
// 5. Сериализуем обратно в байты
|
||||||
|
response.to_vec().ok()
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
use lru::LruCache;
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
use std::num::NonZeroUsize;
|
||||||
|
|
||||||
|
pub struct FakeIpStore {
|
||||||
|
cache: LruCache<String, Ipv4Addr>,
|
||||||
|
pub rev_cache: LruCache<Ipv4Addr, String>,
|
||||||
|
next_ip: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
const START_IP: u32 = 0x64400001; // 100.64.0.1 (IP for Service Networks/Shared Address Space)
|
||||||
|
|
||||||
|
impl FakeIpStore {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
cache: LruCache::new(NonZeroUsize::new(2000).unwrap()),
|
||||||
|
rev_cache: LruCache::new(NonZeroUsize::new(2000).unwrap()),
|
||||||
|
next_ip: START_IP,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_or_assign(&mut self, host: &str) -> Ipv4Addr {
|
||||||
|
if let Some(&ip) = self.cache.get(host) {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
let ip = Ipv4Addr::from(self.next_ip);
|
||||||
|
self.next_ip += 1;
|
||||||
|
self.cache.put(host.to_string(), ip);
|
||||||
|
self.rev_cache.put(ip, host.to_string());
|
||||||
|
ip
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lookup_by_ip(&self, ip: &Ipv4Addr) -> Option<String> {
|
||||||
|
self.rev_cache.peek(ip).cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1,4 @@
|
|||||||
|
pub mod dns;
|
||||||
|
pub mod ip_store;
|
||||||
pub mod tcp_connection;
|
pub mod tcp_connection;
|
||||||
|
pub mod udp_connection;
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
use netrunner_common::protocol::codec::socks::SocksRequest;
|
use netrunner_common::protocol::codec::socks::{SocksRequest, TargetAddress};
|
||||||
use smoltcp::iface::SocketHandle;
|
use smoltcp::iface::SocketHandle;
|
||||||
use smoltcp::socket::tcp;
|
use smoltcp::socket::tcp;
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
use tokio::net::TcpStream; // Твой код парсера
|
use tokio::net::TcpStream; // Твой код парсера
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
use tracing::{debug, info, trace};
|
||||||
|
|
||||||
pub enum ConnectionState {
|
pub enum ConnectionState {
|
||||||
/// Сокет только что принял соединение (SYN-ACK завершен)
|
|
||||||
Established,
|
Established,
|
||||||
/// Мы в процессе SOCKS5 рукопожатия с локальным прокси
|
|
||||||
Handshaking,
|
Handshaking,
|
||||||
/// Соединение готово к передаче данных (Bridge)
|
|
||||||
Active,
|
Active,
|
||||||
/// Ошибка или закрытие
|
|
||||||
Closed,
|
Closed,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,33 +18,46 @@ pub struct TcpConnection {
|
|||||||
state: ConnectionState,
|
state: ConnectionState,
|
||||||
tx: mpsc::UnboundedSender<Vec<u8>>,
|
tx: mpsc::UnboundedSender<Vec<u8>>,
|
||||||
rx: mpsc::UnboundedReceiver<Vec<u8>>,
|
rx: mpsc::UnboundedReceiver<Vec<u8>>,
|
||||||
|
pending_data: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpConnection {
|
impl TcpConnection {
|
||||||
pub fn new(
|
pub fn new(handle: SocketHandle, proxy_addr: String, target_addr: TargetAddress) -> Self {
|
||||||
handle: SocketHandle,
|
|
||||||
proxy_addr: String,
|
|
||||||
target_addr: std::net::SocketAddr,
|
|
||||||
) -> Self {
|
|
||||||
let (tx_to_proxy, mut rx_from_smol) = mpsc::unbounded_channel::<Vec<u8>>();
|
let (tx_to_proxy, mut rx_from_smol) = mpsc::unbounded_channel::<Vec<u8>>();
|
||||||
let (tx_to_smol, rx_from_proxy) = mpsc::unbounded_channel::<Vec<u8>>();
|
let (tx_to_smol, rx_from_proxy) = mpsc::unbounded_channel::<Vec<u8>>();
|
||||||
|
|
||||||
// Запускаем асинхронную логику в фоне
|
let proxy_addr_clone = proxy_addr.clone();
|
||||||
|
let target_addr_clone = target_addr.clone();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
// 1. Подключаемся
|
debug!(
|
||||||
|
%handle,
|
||||||
|
target = ?target_addr_clone,
|
||||||
|
proxy = %proxy_addr_clone,
|
||||||
|
"Attempting to connect through proxy"
|
||||||
|
);
|
||||||
|
|
||||||
let mut stream = match TcpStream::connect(&proxy_addr).await {
|
let mut stream = match TcpStream::connect(&proxy_addr).await {
|
||||||
Ok(s) => s,
|
Ok(s) => {
|
||||||
Err(_) => return, // Тут можно добавить логирование
|
debug!(%handle, "Connected to proxy successfully");
|
||||||
|
s
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
debug!(%handle, error = %e, "Failed to connect to proxy");
|
||||||
|
return;
|
||||||
|
} // Тут можно добавить логирование
|
||||||
};
|
};
|
||||||
|
|
||||||
// 2. SOCKS Handshake
|
// 2. SOCKS Handshake
|
||||||
if SocksRequest::perform_client_handshake(&mut stream, &target_addr)
|
if let Err(e) =
|
||||||
.await
|
SocksRequest::perform_client_handshake(&mut stream, &target_addr_clone).await
|
||||||
.is_err()
|
|
||||||
{
|
{
|
||||||
|
debug!(%handle, error = %e, "SOCKS handshake failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!(%handle, "SOCKS handshake successful, starting data bridge");
|
||||||
|
|
||||||
// 3. Копирование данных (Bridge)
|
// 3. Копирование данных (Bridge)
|
||||||
let (mut reader, mut writer) = stream.into_split();
|
let (mut reader, mut writer) = stream.into_split();
|
||||||
|
|
||||||
@@ -83,29 +93,87 @@ impl TcpConnection {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
handle,
|
handle,
|
||||||
state: ConnectionState::Active, // Сразу переходим в Active, т.к. задача пошла
|
state: ConnectionState::Handshaking, // Сразу переходим в Active, т.к. задача пошла
|
||||||
tx: tx_to_proxy,
|
tx: tx_to_proxy,
|
||||||
rx: rx_from_proxy,
|
rx: rx_from_proxy,
|
||||||
|
pending_data: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tick(&mut self, socket: &mut tcp::Socket) -> bool {
|
||||||
|
trace!(handle=%self.handle, state=?socket.state(), "Tick");
|
||||||
|
match self.state {
|
||||||
|
ConnectionState::Handshaking => {
|
||||||
|
info!("Connection handshaking");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ConnectionState::Active => {
|
||||||
|
self.poll_and_process(socket);
|
||||||
|
|
||||||
|
// Проверяем условия закрытия
|
||||||
|
if self.is_finished(socket) {
|
||||||
|
self.state = ConnectionState::Closed;
|
||||||
|
socket.abort(); // Принудительно разрываем стек
|
||||||
|
return false; // Сигнализируем, что соединение мертво
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConnectionState::Closed => return false,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_finished(&self, socket: &tcp::Socket) -> bool {
|
||||||
|
use tcp::State;
|
||||||
|
let socket_closed = matches!(
|
||||||
|
socket.state(),
|
||||||
|
State::Closed | State::TimeWait | State::FinWait1 | State::FinWait2
|
||||||
|
);
|
||||||
|
|
||||||
|
let task_finished = self.rx.is_closed();
|
||||||
|
|
||||||
|
socket_closed || task_finished
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_active(&self) -> bool {
|
||||||
|
matches!(self.state, ConnectionState::Active)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_and_process(&mut self, socket: &mut tcp::Socket) {
|
||||||
|
if let Some(data) = self.pending_data.take() {
|
||||||
|
if socket.send_slice(&data).is_ok() {
|
||||||
|
} else {
|
||||||
|
self.pending_data = Some(data);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_and_process(&mut self, socket: &mut tcp::Socket) {
|
|
||||||
// 1. Из smoltcp -> В канал задачи
|
|
||||||
if socket.can_recv() {
|
if socket.can_recv() {
|
||||||
let mut buf = [0u8; 4096];
|
let _ = socket.recv(|data| {
|
||||||
if let Ok(n) = socket.recv_slice(&mut buf) {
|
let len = data.len();
|
||||||
if n > 0 {
|
if len > 0 {
|
||||||
let _ = self.tx.send(buf[..n].to_vec());
|
let _ = self.tx.send(data.to_vec());
|
||||||
|
}
|
||||||
|
(len, ())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if socket.can_send() {
|
||||||
|
while let Ok(data) = self.rx.try_recv() {
|
||||||
|
match socket.send_slice(&data) {
|
||||||
|
Ok(_) => { /* Успешно */ }
|
||||||
|
Err(_) => {
|
||||||
|
// Стек полон, запоминаем данные для следующего вызова
|
||||||
|
self.pending_data = Some(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Из канала задачи -> В smoltcp
|
if socket.state() == tcp::State::CloseWait {
|
||||||
if socket.can_send() {
|
debug!(handle=%self.handle, "!!! Triggering socket.close() for CLOSE-WAIT");
|
||||||
// try_recv не блокирует поток, что нам и нужно
|
socket.close();
|
||||||
if let Ok(data) = self.rx.try_recv() {
|
|
||||||
let _ = socket.send_slice(&data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
use crate::connections::dns::handle_dns_query;
|
||||||
|
use crate::connections::ip_store::FakeIpStore;
|
||||||
|
use smoltcp::socket::udp;
|
||||||
|
|
||||||
|
pub struct UdpConnection;
|
||||||
|
|
||||||
|
impl UdpConnection {
|
||||||
|
pub fn process_incoming(socket: &mut udp::Socket, store: &mut FakeIpStore) {
|
||||||
|
// Мы используем peek или recv, чтобы понять, куда идти дальше
|
||||||
|
while socket.can_recv() {
|
||||||
|
let (data, metadata) = match socket.recv() {
|
||||||
|
Ok(res) => res,
|
||||||
|
Err(_) => break,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Диспетчер: определяем тип трафика по порту
|
||||||
|
match metadata.endpoint.port {
|
||||||
|
53 => {
|
||||||
|
// Это DNS
|
||||||
|
if let Some(response) = handle_dns_query(&data, store) {
|
||||||
|
let _ = socket.send_slice(&response, metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Тут в будущем можно добавить обработку других протоколов
|
||||||
|
// 443 => process_quic(...),
|
||||||
|
_ => {
|
||||||
|
// Можно логировать неизвестный трафик или просто дропать
|
||||||
|
// trace!("Received UDP on unknown port: {}", endpoint.port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-5
@@ -1,3 +1,5 @@
|
|||||||
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
use netrunner_client::{tun::engine::Engine, tun::tun::Tun};
|
use netrunner_client::{tun::engine::Engine, tun::tun::Tun};
|
||||||
use netrunner_common::{
|
use netrunner_common::{
|
||||||
logger_init,
|
logger_init,
|
||||||
@@ -21,8 +23,7 @@ async fn main() {
|
|||||||
})
|
})
|
||||||
.expect("Failed to initialize TUN device");
|
.expect("Failed to initialize TUN device");
|
||||||
|
|
||||||
tun_device.clear_default_route();
|
tun_device.setup_routing();
|
||||||
tun_device.setup_linux_routes();
|
|
||||||
|
|
||||||
info!("TUN interface is UP: 10.0.0.1/24");
|
info!("TUN interface is UP: 10.0.0.1/24");
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ async fn main() {
|
|||||||
|
|
||||||
let network = Network::new(8080, ConnectionRole::Client, Some(remote_address));
|
let network = Network::new(8080, ConnectionRole::Client, Some(remote_address));
|
||||||
|
|
||||||
let socks_addr = network.get_self_local_address();
|
let proxy_ip = network.get_self_local_address();
|
||||||
|
|
||||||
// 2. ВЫНОСИМ СЕТЬ В ОТДЕЛЬНЫЙ ЦИКЛ
|
// 2. ВЫНОСИМ СЕТЬ В ОТДЕЛЬНЫЙ ЦИКЛ
|
||||||
// Это запустит SOCKS5 сервер и TLS туннель параллельно движку
|
// Это запустит SOCKS5 сервер и TLS туннель параллельно движку
|
||||||
@@ -44,10 +45,11 @@ async fn main() {
|
|||||||
network.run().await;
|
network.run().await;
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut engine = Engine::new(config, caps, socks_addr);
|
let mut engine = Engine::new(config, caps, proxy_ip);
|
||||||
engine.set_any_ip(true);
|
engine.set_any_ip(true);
|
||||||
engine.set_transparent_mode();
|
engine.set_transparent_mode();
|
||||||
|
engine.set_default_gateway(Ipv4Addr::new(10, 0, 0, 2)); // to smoltcp
|
||||||
|
engine.activate();
|
||||||
info!("Stack IP initialized: 10.0.0.2");
|
info!("Stack IP initialized: 10.0.0.2");
|
||||||
|
|
||||||
// 5. Запуск
|
// 5. Запуск
|
||||||
|
|||||||
@@ -1,19 +1,26 @@
|
|||||||
|
use netrunner_common::protocol::codec::socks::TargetAddress;
|
||||||
use smoltcp::{
|
use smoltcp::{
|
||||||
iface::{SocketHandle, SocketSet},
|
iface::{SocketHandle, SocketSet},
|
||||||
socket::{AnySocket, icmp, tcp, udp},
|
socket::{AnySocket, icmp, tcp, udp},
|
||||||
wire::IpListenEndpoint,
|
wire::{IpAddress, IpListenEndpoint},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
time::{Duration, Instant as StdInstant},
|
time::{Duration, Instant as StdInstant},
|
||||||
};
|
};
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use crate::{connections::tcp_connection::TcpConnection, tun::engine::START_TIME};
|
use crate::{
|
||||||
|
connections::{
|
||||||
|
ip_store::FakeIpStore, tcp_connection::TcpConnection, udp_connection::UdpConnection,
|
||||||
|
},
|
||||||
|
tun::engine::START_TIME,
|
||||||
|
};
|
||||||
pub struct ConnectionManager {
|
pub struct ConnectionManager {
|
||||||
last_activity: HashMap<SocketHandle, StdInstant>,
|
last_activity: HashMap<SocketHandle, StdInstant>,
|
||||||
active_tcp_sessions: HashMap<SocketHandle, TcpConnection>,
|
active_tcp_sessions: HashMap<SocketHandle, TcpConnection>,
|
||||||
//active_udp_sessions: HashMap<SocketHandle, UdpSession>,
|
//active_udp_sessions: HashMap<SocketHandle, UdpSession>,
|
||||||
|
fake_ip_store: FakeIpStore,
|
||||||
proxy_ip: String,
|
proxy_ip: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,79 +30,113 @@ impl ConnectionManager {
|
|||||||
last_activity: HashMap::new(),
|
last_activity: HashMap::new(),
|
||||||
active_tcp_sessions: HashMap::new(),
|
active_tcp_sessions: HashMap::new(),
|
||||||
proxy_ip: ip,
|
proxy_ip: ip,
|
||||||
|
fake_ip_store: FakeIpStore::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Основной метод, который вызывается в цикле Engine
|
pub fn start_listening(&mut self, socket_set: &mut SocketSet) {
|
||||||
pub fn process_sockets(&mut self, socket_set: &mut SocketSet) {
|
for (_, socket) in socket_set.iter_mut() {
|
||||||
for (handle, socket) in socket_set.iter_mut() {
|
|
||||||
// 1. Пытаемся даункастить сокет до TCP
|
|
||||||
if let Some(tcp) = tcp::Socket::downcast_mut(socket) {
|
if let Some(tcp) = tcp::Socket::downcast_mut(socket) {
|
||||||
self.handle_tcp(handle, tcp);
|
if !tcp.is_open() {
|
||||||
continue;
|
let endpoint = IpListenEndpoint {
|
||||||
}
|
addr: None,
|
||||||
|
port: 443,
|
||||||
// 2. До UDP
|
|
||||||
if let Some(udp) = udp::Socket::downcast_mut(socket) {
|
|
||||||
self.handle_udp(handle, udp);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. До ICMP
|
|
||||||
if let Some(icmp) = icmp::Socket::downcast_mut(socket) {
|
|
||||||
self.handle_icmp(handle, icmp);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn handle_tcp(&mut self, handle: SocketHandle, socket: &mut tcp::Socket) {
|
|
||||||
if socket.state() == tcp::State::Established {
|
|
||||||
let proxy_ip = self.proxy_ip.clone(); // Берем из конфига менеджера
|
|
||||||
|
|
||||||
let conn = self.active_tcp_sessions.entry(handle).or_insert_with(|| {
|
|
||||||
// 1. Получаем endpoint и безопасно распаковываем его
|
|
||||||
let endpoint = socket
|
|
||||||
.remote_endpoint()
|
|
||||||
.expect("TCP socket in Established state must have a remote endpoint");
|
|
||||||
|
|
||||||
// 2. Конвертируем smoltcp::wire::IpAddress в std::net::IpAddr
|
|
||||||
let ip: std::net::IpAddr = match endpoint.addr {
|
|
||||||
smoltcp::wire::IpAddress::Ipv4(v4) => std::net::IpAddr::V4(v4.into()),
|
|
||||||
smoltcp::wire::IpAddress::Ipv6(v6) => std::net::IpAddr::V6(v6.into()),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 3. Собираем финальный SocketAddr
|
match tcp.listen(endpoint) {
|
||||||
let target_addr = std::net::SocketAddr::new(ip, endpoint.port);
|
Ok(_) => debug!("Socket is now listening"),
|
||||||
|
Err(e) => warn!(error=?e, "Failed to listen on socket"),
|
||||||
info!(handle=%handle, target=%target_addr, "Creating new TcpConnection bridge");
|
|
||||||
TcpConnection::new(handle, proxy_ip, target_addr)
|
|
||||||
});
|
|
||||||
|
|
||||||
conn.poll_and_process(socket);
|
|
||||||
}
|
}
|
||||||
if socket.state() == tcp::State::Closed {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_target(&self, socket: &tcp::Socket) -> TargetAddress {
|
||||||
|
// Безопасно получаем эндпоинт
|
||||||
|
let remote_endpoint = match socket.remote_endpoint() {
|
||||||
|
Some(ep) => ep,
|
||||||
|
None => {
|
||||||
|
warn!(handle=?socket, "Attempted to resolve target for an unconnected socket");
|
||||||
|
// Возвращаем дефолт, чтобы не падать
|
||||||
|
return TargetAddress::Domain("disconnected".to_string(), 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let port = remote_endpoint.port;
|
||||||
|
let ip = remote_endpoint.addr;
|
||||||
|
|
||||||
|
match ip {
|
||||||
|
smoltcp::wire::IpAddress::Ipv4(ipv4_addr) => {
|
||||||
|
let std_ip = std::net::Ipv4Addr::from(ipv4_addr);
|
||||||
|
|
||||||
|
// Ищем домен в нашем FakeIpStore
|
||||||
|
if let Some(domain) = self.fake_ip_store.lookup_by_ip(&std_ip) {
|
||||||
|
debug!(target=%domain, port=%port, "Resolved fake IP to domain");
|
||||||
|
return TargetAddress::Domain(domain, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!(ip=%std_ip, port=%port, "Using raw IP target");
|
||||||
|
TargetAddress::Ipv4(std_ip, port)
|
||||||
|
}
|
||||||
|
smoltcp::wire::IpAddress::Ipv6(ipv6_addr) => {
|
||||||
|
let std_ip = std::net::Ipv6Addr::from(ipv6_addr);
|
||||||
|
debug!(ip=%std_ip, port=%port, "Using IPv6 target");
|
||||||
|
TargetAddress::Ipv6(std_ip, port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn process_sockets(&mut self, socket_set: &mut SocketSet) {
|
||||||
|
for (handle, socket) in socket_set.iter_mut() {
|
||||||
|
if let Some(tcp) = tcp::Socket::downcast_mut(socket) {
|
||||||
|
self.handle_tcp(handle, tcp);
|
||||||
|
} else if let Some(udp) = udp::Socket::downcast_mut(socket) {
|
||||||
|
self.handle_udp(handle, udp);
|
||||||
|
} else if let Some(icmp) = icmp::Socket::downcast_mut(socket) {
|
||||||
|
self.handle_icmp(handle, icmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_tcp(&mut self, handle: SocketHandle, socket: &mut tcp::Socket) {
|
||||||
|
if socket.state() == tcp::State::Established {
|
||||||
|
let target = self.resolve_target(socket);
|
||||||
|
debug!(
|
||||||
|
handle=%handle,
|
||||||
|
local=?socket.local_endpoint(),
|
||||||
|
remote=?socket.remote_endpoint(),
|
||||||
|
"Socket details"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut conn = TcpConnection::new(handle, self.proxy_ip.clone(), target);
|
||||||
|
|
||||||
|
conn.tick(socket);
|
||||||
|
|
||||||
|
if conn.is_active() {
|
||||||
|
self.active_tcp_sessions.insert(handle, conn);
|
||||||
|
} else {
|
||||||
|
socket.abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(conn) = self.active_tcp_sessions.get_mut(&handle) {
|
||||||
|
if !conn.tick(socket) {
|
||||||
self.active_tcp_sessions.remove(&handle);
|
self.active_tcp_sessions.remove(&handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_udp(&mut self, handle: SocketHandle, socket: &mut udp::Socket) {
|
fn handle_udp(&mut self, handle: SocketHandle, socket: &mut udp::Socket) {
|
||||||
if socket.can_recv() {
|
self.last_activity.insert(handle, StdInstant::now());
|
||||||
match socket.recv() {
|
|
||||||
Ok((data, endpoint)) => {
|
UdpConnection::process_incoming(socket, &mut self.fake_ip_store);
|
||||||
info!(handle=%handle, from=?endpoint, len=data.len(), "UDP: packet received");
|
|
||||||
// МОК: Обработка UDP датаграммы
|
|
||||||
}
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_icmp(&mut self, handle: SocketHandle, socket: &mut icmp::Socket) {
|
fn handle_icmp(&mut self, handle: SocketHandle, socket: &mut icmp::Socket) {
|
||||||
if socket.can_recv() {
|
if socket.can_recv() {
|
||||||
match socket.recv() {
|
match socket.recv() {
|
||||||
Ok((data, endpoint)) => {
|
Ok((data, endpoint)) => {
|
||||||
debug!(handle=%handle, from=?endpoint, "ICMP: packet received");
|
debug!(handle=%handle, from=?endpoint, data=?data, "ICMP: packet received");
|
||||||
// МОК: Ответ на пинг или обработка ошибок
|
|
||||||
}
|
}
|
||||||
Err(_) => {}
|
Err(_) => {}
|
||||||
}
|
}
|
||||||
@@ -126,106 +167,25 @@ impl ConnectionManager {
|
|||||||
icmp::Socket::new(icmp_rx_buffer, icmp_tx_buffer)
|
icmp::Socket::new(icmp_rx_buffer, icmp_tx_buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refill_sockets(&mut self, socket_set: &mut SocketSet) {
|
pub fn setup_sockets(n_tcp: usize, n_udp: usize, n_icmp: usize) -> SocketSet<'static> {
|
||||||
self.prune_sockets(socket_set);
|
// Создаем хранилище с запасом на все типы сокетов
|
||||||
const TARGET_FREE_TCP: usize = 16;
|
let mut sockets = SocketSet::new(Vec::with_capacity(n_tcp + n_udp + n_icmp));
|
||||||
const TARGET_FREE_UDP: usize = 8;
|
|
||||||
|
|
||||||
for &port in &[80, 443, 8080] {
|
// 1. Добавляем TCP сокеты
|
||||||
let current_port_sockets = socket_set
|
for _ in 0..n_tcp {
|
||||||
.iter()
|
sockets.add(Self::create_tcp_socket());
|
||||||
.filter(|(_, s)| {
|
|
||||||
if let Some(tcp) = tcp::Socket::downcast(s) {
|
|
||||||
// Если эндпоинт есть - сверяем порт
|
|
||||||
if let Some(endpoint) = tcp.local_endpoint() {
|
|
||||||
return endpoint.port == port;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// КЛЮЧЕВОЙ МОМЕНТ:
|
// 2. Добавляем UDP сокеты
|
||||||
// Если эндпоинта НЕТ, но сокет НЕ в состоянии CLOSED,
|
for _ in 0..n_udp {
|
||||||
// или он только что был создан для прослушивания.
|
sockets.add(Self::create_udp_socket());
|
||||||
// В smoltcp после listen() сокет переходит в LISTEN,
|
|
||||||
// но local_endpoint может появиться чуть позже.
|
|
||||||
tcp.state() == tcp::State::Listen
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.count();
|
|
||||||
|
|
||||||
if current_port_sockets < 5 {
|
|
||||||
let mut s = Self::create_tcp_socket();
|
|
||||||
let endpoint = IpListenEndpoint { addr: None, port };
|
|
||||||
|
|
||||||
// Попробуй сначала listen, а потом добавлять
|
|
||||||
if s.listen(endpoint).is_ok() {
|
|
||||||
socket_set.add(s);
|
|
||||||
info!(
|
|
||||||
"--- REAL ADD --- Port: {}, Sockets for this port: {}",
|
|
||||||
port,
|
|
||||||
current_port_sockets + 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let udp_active = socket_set
|
// 3. Добавляем ICMP сокет
|
||||||
.iter()
|
for _ in 0..n_icmp {
|
||||||
.filter(|(_, s)| udp::Socket::downcast(s).is_some())
|
sockets.add(Self::create_icmp_socket());
|
||||||
.count();
|
|
||||||
|
|
||||||
let has_icmp = socket_set
|
|
||||||
.iter()
|
|
||||||
.any(|(_, s)| icmp::Socket::downcast(s).is_some());
|
|
||||||
|
|
||||||
if udp_active < TARGET_FREE_UDP {
|
|
||||||
let diff = TARGET_FREE_UDP - udp_active;
|
|
||||||
debug!("Refilling UDP pool: adding {} sockets", diff);
|
|
||||||
for _ in 0..diff {
|
|
||||||
let s = Self::create_udp_socket();
|
|
||||||
socket_set.add(s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !has_icmp {
|
sockets
|
||||||
debug!("Adding ICMP socket for echo requests");
|
|
||||||
let s = Self::create_icmp_socket();
|
|
||||||
socket_set.add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prune_sockets(&mut self, socket_set: &mut SocketSet) {
|
|
||||||
let now = StdInstant::now();
|
|
||||||
let udp_timeout = Duration::from_secs(60); // 1 минута для UDP
|
|
||||||
let mut to_remove = Vec::new();
|
|
||||||
|
|
||||||
for (handle, socket) in socket_set.iter() {
|
|
||||||
if let Some(tcp) = tcp::Socket::downcast(socket) {
|
|
||||||
if tcp.state() == tcp::State::Closed {
|
|
||||||
to_remove.push(handle);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(udp) = udp::Socket::downcast(socket) {
|
|
||||||
if udp.endpoint().port == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let last = self.last_activity.get(&handle).unwrap_or(&START_TIME);
|
|
||||||
if now.duration_since(*last) > udp_timeout {
|
|
||||||
debug!(handle=%handle, "UDP socket timeout reached");
|
|
||||||
to_remove.push(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(_icmp) = icmp::Socket::downcast(socket) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for handle in to_remove {
|
|
||||||
socket_set.remove(handle);
|
|
||||||
self.last_activity.remove(&handle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ use smoltcp::{
|
|||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
use tracing::trace;
|
||||||
|
|
||||||
pub struct VirtTunDevice {
|
pub struct VirtTunDevice {
|
||||||
capabilities: DeviceCapabilities,
|
capabilities: DeviceCapabilities,
|
||||||
@@ -63,6 +64,7 @@ impl Device for VirtTunDevice {
|
|||||||
|
|
||||||
fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
||||||
if let Ok(buffer) = self.in_buf.try_recv() {
|
if let Ok(buffer) = self.in_buf.try_recv() {
|
||||||
|
trace!("--- TUN RX: {} bytes ---", buffer.len()); // Посмотри, что именно прилетает
|
||||||
let rx = Self::RxToken {
|
let rx = Self::RxToken {
|
||||||
buffer,
|
buffer,
|
||||||
phantom_device: PhantomData,
|
phantom_device: PhantomData,
|
||||||
|
|||||||
+29
-32
@@ -1,4 +1,5 @@
|
|||||||
use smoltcp::time::Instant;
|
use smoltcp::time::Instant;
|
||||||
|
use smoltcp::wire::{IpAddress, IpCidr};
|
||||||
use smoltcp::{
|
use smoltcp::{
|
||||||
iface::{Config, Interface, SocketSet},
|
iface::{Config, Interface, SocketSet},
|
||||||
phy::DeviceCapabilities,
|
phy::DeviceCapabilities,
|
||||||
@@ -35,9 +36,10 @@ impl Engine {
|
|||||||
pub fn new(config: Config, caps: DeviceCapabilities, ip: String) -> Self {
|
pub fn new(config: Config, caps: DeviceCapabilities, ip: String) -> Self {
|
||||||
let now = Engine::current_time();
|
let now = Engine::current_time();
|
||||||
let (mut device, bridge_rx, bridge_tx, avail) = VirtTunDevice::new(caps);
|
let (mut device, bridge_rx, bridge_tx, avail) = VirtTunDevice::new(caps);
|
||||||
let mut interface = Interface::new(config, &mut device, now);
|
let interface = Interface::new(config, &mut device, now);
|
||||||
|
|
||||||
let socket_set = SocketSet::new(vec![]);
|
let mut socket_set = ConnectionManager::setup_sockets(16, 4, 1);
|
||||||
|
let mut manager = ConnectionManager::new(ip);
|
||||||
Self {
|
Self {
|
||||||
interface,
|
interface,
|
||||||
socket_set,
|
socket_set,
|
||||||
@@ -45,11 +47,12 @@ impl Engine {
|
|||||||
bridge_tx,
|
bridge_tx,
|
||||||
bridge_rx,
|
bridge_rx,
|
||||||
avail,
|
avail,
|
||||||
manager: ConnectionManager::new(ip),
|
manager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(&mut self, tun: Tun) {
|
pub async fn run(&mut self, tun: Tun) {
|
||||||
|
info!("Current routes: {:?}", self.interface.routes());
|
||||||
//Bridge from tun to stack and stack to tun
|
//Bridge from tun to stack and stack to tun
|
||||||
let (writer, reader) = tun.split().expect("Failed to split TUN");
|
let (writer, reader) = tun.split().expect("Failed to split TUN");
|
||||||
// Забираем bridge_rx, так как он нам нужен только в одной задаче
|
// Забираем bridge_rx, так как он нам нужен только в одной задаче
|
||||||
@@ -58,9 +61,11 @@ impl Engine {
|
|||||||
Self::spawn_engine_to_tun(writer, from_engine);
|
Self::spawn_engine_to_tun(writer, from_engine);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
self.manager.refill_sockets(&mut self.socket_set);
|
loop {
|
||||||
self.poll();
|
self.poll();
|
||||||
|
|
||||||
self.manager.process_sockets(&mut self.socket_set);
|
self.manager.process_sockets(&mut self.socket_set);
|
||||||
|
|
||||||
if self.avail.load(std::sync::atomic::Ordering::Acquire) {
|
if self.avail.load(std::sync::atomic::Ordering::Acquire) {
|
||||||
tokio::task::yield_now().await;
|
tokio::task::yield_now().await;
|
||||||
continue;
|
continue;
|
||||||
@@ -68,15 +73,15 @@ impl Engine {
|
|||||||
self.poll_delay().await;
|
self.poll_delay().await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn poll(&mut self) {
|
fn poll(&mut self) {
|
||||||
let now = Self::current_time();
|
let now = Self::current_time();
|
||||||
// Передаем девайс и сокеты в интерфейс
|
|
||||||
self.interface
|
self.interface
|
||||||
.poll(now, &mut self.device, &mut self.socket_set);
|
.poll(now, &mut self.device, &mut self.socket_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn poll_delay(&mut self) {
|
async fn poll_delay(&mut self) {
|
||||||
let timestamp = Self::current_time();
|
let timestamp = Self::current_time();
|
||||||
let delay = self.interface.poll_delay(timestamp, &self.socket_set);
|
let delay = self.interface.poll_delay(timestamp, &self.socket_set);
|
||||||
let sleep_duration = match delay {
|
let sleep_duration = match delay {
|
||||||
@@ -99,6 +104,13 @@ impl Engine {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if n >= 20 {
|
||||||
|
let dst_ip = std::net::Ipv4Addr::new(buf[16], buf[17], buf[18], buf[19]);
|
||||||
|
let dst_port = u16::from_be_bytes([buf[22], buf[23]]); // Порт для TCP
|
||||||
|
|
||||||
|
debug!("Сырой пакет: назначение {}:{}", dst_ip, dst_port);
|
||||||
|
}
|
||||||
|
|
||||||
let mut token = TokenBuffer::with_capacity(n);
|
let mut token = TokenBuffer::with_capacity(n);
|
||||||
token.extend_from_slice(&buf[..n]);
|
token.extend_from_slice(&buf[..n]);
|
||||||
|
|
||||||
@@ -132,42 +144,20 @@ impl Engine {
|
|||||||
Instant::from_micros(duration.as_micros() as i64)
|
Instant::from_micros(duration.as_micros() as i64)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_address(&mut self, address: smoltcp::wire::IpCidr) {
|
|
||||||
self.interface.update_ip_addrs(|addrs| {
|
|
||||||
addrs
|
|
||||||
.push(address)
|
|
||||||
.expect("Failed to add IP: address list is full");
|
|
||||||
});
|
|
||||||
self.interface
|
|
||||||
.routes_mut()
|
|
||||||
.add_default_ipv4_route(smoltcp::wire::Ipv4Address::new(10, 0, 0, 1))
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_any_ip(&mut self, state: bool) -> () {
|
pub fn set_any_ip(&mut self, state: bool) -> () {
|
||||||
self.interface.set_any_ip(state)
|
self.interface.set_any_ip(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_transparent_mode(&mut self) {
|
pub fn set_transparent_mode(&mut self) {
|
||||||
info!("Switching engine to transparent mode (AnyIP + 0.0.0.0/0)");
|
|
||||||
|
|
||||||
self.interface.set_any_ip(true);
|
|
||||||
self.interface.update_ip_addrs(|addrs| {
|
self.interface.update_ip_addrs(|addrs| {
|
||||||
addrs.clear();
|
addrs.clear();
|
||||||
|
//accept all internet
|
||||||
addrs
|
addrs
|
||||||
.push(smoltcp::wire::IpCidr::new(
|
.push(IpCidr::new(IpAddress::v4(10, 0, 0, 2), 24))
|
||||||
smoltcp::wire::IpAddress::v4(0, 0, 0, 0),
|
.unwrap();
|
||||||
0,
|
|
||||||
))
|
|
||||||
.expect("Failed to set 0.0.0.0/0");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Устанавливаем дефолтный маршрут "в никуда" (локально)
|
|
||||||
self.interface.routes_mut().remove_default_ipv4_route();
|
self.interface.routes_mut().remove_default_ipv4_route();
|
||||||
self.interface
|
|
||||||
.routes_mut()
|
|
||||||
.add_default_ipv4_route(smoltcp::wire::Ipv4Address::new(0, 0, 0, 0))
|
|
||||||
.ok();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_default_gateway(&mut self, gateway: smoltcp::wire::Ipv4Address) {
|
pub fn set_default_gateway(&mut self, gateway: smoltcp::wire::Ipv4Address) {
|
||||||
@@ -178,4 +168,11 @@ impl Engine {
|
|||||||
.add_default_ipv4_route(gateway)
|
.add_default_ipv4_route(gateway)
|
||||||
.expect("Failed to set default gateway");
|
.expect("Failed to set default gateway");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn activate(&mut self) {
|
||||||
|
let now = Self::current_time();
|
||||||
|
self.interface
|
||||||
|
.poll(now, &mut self.device, &mut self.socket_set);
|
||||||
|
self.manager.start_listening(&mut self.socket_set);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-27
@@ -43,37 +43,19 @@ impl Tun {
|
|||||||
Ok((writer, reader))
|
Ok((writer, reader))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_linux_routes(&self) -> io::Result<()> {
|
pub fn setup_routing(&self) -> io::Result<()> {
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
// Направляем трафик через IP, который слушает твой smoltcp Engine
|
// Теперь, когда мы знаем, что tun0 имеет IP 10.0.0.1,
|
||||||
// Предположим, smoltcp настроен на 10.0.0.2
|
// мы можем смело ставить его шлюзом.
|
||||||
let status = Command::new("ip")
|
|
||||||
.args(&["route", "add", "default", "via", "10.0.0.2", "dev", "tun0"])
|
|
||||||
.status()?;
|
|
||||||
|
|
||||||
if !status.success() {
|
// 1. Устанавливаем маршрут через созданный интерфейс tun0
|
||||||
return Err(io::Error::new(
|
let _ = Command::new("sudo")
|
||||||
io::ErrorKind::Other,
|
.args(&[
|
||||||
"Failed to setup routes",
|
"ip", "route", "add", "default", "via", "10.0.0.2", "dev", "tun0", "metric", "1",
|
||||||
));
|
])
|
||||||
}
|
.status();
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_default_route(&self) -> io::Result<()> {
|
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
info!("Removing existing default route...");
|
|
||||||
|
|
||||||
// Удаляем текущий маршрут по умолчанию
|
|
||||||
let status = Command::new("sudo")
|
|
||||||
.args(&["ip", "route", "del", "default"])
|
|
||||||
.status()?;
|
|
||||||
|
|
||||||
if !status.success() {
|
|
||||||
warn!("Could not delete default route (maybe it doesn't exist?)");
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ impl SocksRequest {
|
|||||||
|
|
||||||
pub async fn perform_client_handshake<S>(
|
pub async fn perform_client_handshake<S>(
|
||||||
stream: &mut S,
|
stream: &mut S,
|
||||||
target_addr: &std::net::SocketAddr,
|
target_addr: &TargetAddress,
|
||||||
) -> Result<(), String>
|
) -> Result<(), String>
|
||||||
where
|
where
|
||||||
S: tokio::io::AsyncReadExt + tokio::io::AsyncWriteExt + Unpin,
|
S: tokio::io::AsyncReadExt + tokio::io::AsyncWriteExt + Unpin,
|
||||||
@@ -90,22 +90,31 @@ impl SocksRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. Формируем CONNECT запрос
|
// 3. Формируем CONNECT запрос
|
||||||
let mut connect_req = BytesMut::with_capacity(10);
|
let mut connect_req = BytesMut::with_capacity(32);
|
||||||
connect_req.put_u8(SOCKS5_VERSION);
|
connect_req.put_u8(SOCKS5_VERSION);
|
||||||
connect_req.put_u8(0x01); // CMD: Connect
|
connect_req.put_u8(0x01); // CMD: Connect
|
||||||
connect_req.put_u8(0x00); // RSV
|
connect_req.put_u8(0x00); // RSV
|
||||||
|
|
||||||
match target_addr {
|
match target_addr {
|
||||||
std::net::SocketAddr::V4(a) => {
|
TargetAddress::Ipv4(ip, port) => {
|
||||||
connect_req.put_u8(ATYP_IPV4);
|
connect_req.put_u8(ATYP_IPV4);
|
||||||
connect_req.put_slice(&a.ip().octets());
|
connect_req.put_slice(&ip.octets());
|
||||||
|
connect_req.put_u16(*port);
|
||||||
}
|
}
|
||||||
std::net::SocketAddr::V6(a) => {
|
TargetAddress::Ipv6(ip, port) => {
|
||||||
connect_req.put_u8(ATYP_IPV6);
|
connect_req.put_u8(ATYP_IPV6);
|
||||||
connect_req.put_slice(&a.ip().octets());
|
connect_req.put_slice(&ip.octets());
|
||||||
|
connect_req.put_u16(*port);
|
||||||
|
}
|
||||||
|
TargetAddress::Domain(host, port) => {
|
||||||
|
connect_req.put_u8(ATYP_DOMAIN);
|
||||||
|
// SOCKS5 для домена требует: [1 байт длина] + [строка]
|
||||||
|
let host_bytes = host.as_bytes();
|
||||||
|
connect_req.put_u8(host_bytes.len() as u8);
|
||||||
|
connect_req.put_slice(host_bytes);
|
||||||
|
connect_req.put_u16(*port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
connect_req.put_u16(target_addr.port());
|
|
||||||
|
|
||||||
stream
|
stream
|
||||||
.write_all(&connect_req)
|
.write_all(&connect_req)
|
||||||
@@ -163,17 +172,16 @@ pub enum SocksReply {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TargetAddress {
|
pub enum TargetAddress {
|
||||||
Ipv4(std::net::Ipv4Addr),
|
Ipv4(std::net::Ipv4Addr, u16), // Теперь 2 поля
|
||||||
Domain(String),
|
Domain(String, u16), // Теперь 2 поля
|
||||||
Ipv6(std::net::Ipv6Addr),
|
Ipv6(std::net::Ipv6Addr, u16), // Теперь 2 поля
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SocksTarget {
|
pub struct SocksTarget {
|
||||||
pub addr: TargetAddress,
|
pub addr: TargetAddress,
|
||||||
pub port: u16,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SocksReply {
|
impl SocksReply {
|
||||||
@@ -203,20 +211,20 @@ impl SocksReply {
|
|||||||
impl SocksTarget {
|
impl SocksTarget {
|
||||||
pub fn to_string(&self) -> String {
|
pub fn to_string(&self) -> String {
|
||||||
match &self.addr {
|
match &self.addr {
|
||||||
// Если это IPv4, у нас уже есть объект Ipv4Addr
|
// Теперь в каждом варианте TargetAddress уже есть порт (port)
|
||||||
TargetAddress::Ipv4(ip) => {
|
TargetAddress::Ipv4(ip, port) => {
|
||||||
format!("{}:{}", ip, self.port)
|
format!("{}:{}", ip, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Если это IPv6, объект Ipv6Addr (автоматически добавит скобки при надобности или используй формат)
|
TargetAddress::Ipv6(ip, port) => {
|
||||||
TargetAddress::Ipv6(ip) => {
|
// IPv6 адреса принято заключать в квадратные скобки при наличии порта
|
||||||
format!("[{}]:{}", ip, self.port)
|
format!("[{}]:{}", ip, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Если это домен, то это String. Вычищаем нули на всякий случай
|
TargetAddress::Domain(domain, port) => {
|
||||||
TargetAddress::Domain(domain) => {
|
// Вычищаем нулевые байты, если они случайно попали в строку
|
||||||
let clean_domain = domain.replace('\0', "");
|
let clean_domain = domain.replace('\0', "");
|
||||||
format!("{}:{}", clean_domain, self.port)
|
format!("{}:{}", clean_domain, port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,21 +6,25 @@ impl Parser for SocksTarget {
|
|||||||
type Error = String;
|
type Error = String;
|
||||||
|
|
||||||
fn can_parse(bytes: &BytesMut) -> bool {
|
fn can_parse(bytes: &BytesMut) -> bool {
|
||||||
if bytes.len() < SOCKS5_MIN_HEADER {
|
// Минимальная длина SOCKS5 CONNECT (VER, CMD, RSV, ATYP) = 4 байта
|
||||||
|
if bytes.len() < 4 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let atyp = bytes[3];
|
let atyp = bytes[3];
|
||||||
match atyp {
|
match atyp {
|
||||||
ATYP_IPV4 => bytes.len() >= SOCKS5_MIN_HEADER + IPV4_SIZE + PORT_SIZE,
|
// IPv4: 4 байта IP + 2 байта порт
|
||||||
|
ATYP_IPV4 => bytes.len() >= 4 + 4 + 2,
|
||||||
|
// IPv6: 16 байт IP + 2 байта порт
|
||||||
|
ATYP_IPV6 => bytes.len() >= 4 + 16 + 2,
|
||||||
|
// Domain: 1 байт длины + N байт домена + 2 байта порт
|
||||||
ATYP_DOMAIN => {
|
ATYP_DOMAIN => {
|
||||||
if bytes.len() < SOCKS5_MIN_HEADER + 1 {
|
if bytes.len() < 5 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let domain_len = bytes[4] as usize;
|
let domain_len = bytes[4] as usize;
|
||||||
bytes.len() >= SOCKS5_MIN_HEADER + 1 + domain_len + PORT_SIZE
|
bytes.len() >= 4 + 1 + domain_len + 2
|
||||||
}
|
}
|
||||||
ATYP_IPV6 => bytes.len() >= SOCKS5_MIN_HEADER + IPV6_SIZE + PORT_SIZE,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,8 +35,7 @@ impl Parser for SocksTarget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let atyp = bytes[3];
|
let atyp = bytes[3];
|
||||||
|
// Вычисляем длину (включая ATYP и порт)
|
||||||
// Вычисляем длину еще раз для split_to (либо можно вынести в хелпер)
|
|
||||||
let total_len = match atyp {
|
let total_len = match atyp {
|
||||||
ATYP_IPV4 => SOCKS5_MIN_HEADER + IPV4_SIZE + PORT_SIZE,
|
ATYP_IPV4 => SOCKS5_MIN_HEADER + IPV4_SIZE + PORT_SIZE,
|
||||||
ATYP_DOMAIN => SOCKS5_MIN_HEADER + 1 + (bytes[4] as usize) + PORT_SIZE,
|
ATYP_DOMAIN => SOCKS5_MIN_HEADER + 1 + (bytes[4] as usize) + PORT_SIZE,
|
||||||
@@ -41,29 +44,32 @@ impl Parser for SocksTarget {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut packet = bytes.split_to(total_len);
|
let mut packet = bytes.split_to(total_len);
|
||||||
packet.advance(SOCKS5_MIN_HEADER);
|
packet.advance(4); // Пропускаем [VER, CMD, RSV, ATYP]
|
||||||
|
|
||||||
let addr = match atyp {
|
let addr = match atyp {
|
||||||
ATYP_IPV4 => {
|
ATYP_IPV4 => {
|
||||||
let octets: [u8; 4] = packet.split_to(4)[..].try_into().unwrap();
|
let octets: [u8; 4] = packet.split_to(4)[..].try_into().unwrap();
|
||||||
TargetAddress::Ipv4(octets.into())
|
let port = packet.get_u16(); // Достаем порт сразу
|
||||||
|
TargetAddress::Ipv4(octets.into(), port)
|
||||||
}
|
}
|
||||||
ATYP_DOMAIN => {
|
ATYP_DOMAIN => {
|
||||||
let len = packet.get_u8() as usize;
|
let len = packet.get_u8() as usize;
|
||||||
let domain_bytes = packet.split_to(len);
|
let domain_bytes = packet.split_to(len);
|
||||||
let domain = String::from_utf8(domain_bytes.to_vec())
|
let domain = String::from_utf8(domain_bytes.to_vec())
|
||||||
.map_err(|_| "Invalid UTF-8 domain".to_string())?;
|
.map_err(|_| "Invalid UTF-8 domain".to_string())?;
|
||||||
TargetAddress::Domain(domain)
|
let port = packet.get_u16(); // Достаем порт сразу
|
||||||
|
TargetAddress::Domain(domain, port)
|
||||||
}
|
}
|
||||||
ATYP_IPV6 => {
|
ATYP_IPV6 => {
|
||||||
let octets: [u8; 16] = packet.split_to(16)[..].try_into().unwrap();
|
let octets: [u8; 16] = packet.split_to(16)[..].try_into().unwrap();
|
||||||
TargetAddress::Ipv6(octets.into())
|
let port = packet.get_u16(); // Достаем порт сразу
|
||||||
|
TargetAddress::Ipv6(octets.into(), port)
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let port = packet.get_u16();
|
// Теперь SocksTarget — это просто оболочка над новым TargetAddress
|
||||||
Ok(Some(SocksTarget { addr, port }))
|
Ok(Some(SocksTarget { addr }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user