diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 408c0f3..0000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,4 +0,0 @@ -[env] -# Each interface needs 1 IP allocated to the WireGuard peer IP. -# "8" = 7 tunnels per protocol. -SMOLTCP_IFACE_MAX_ADDR_COUNT = "8" diff --git a/.github/ci/macos-install-packages b/.github/ci/macos-install-packages index a4ece81..afb1102 100755 --- a/.github/ci/macos-install-packages +++ b/.github/ci/macos-install-packages @@ -1,6 +1,6 @@ #!/bin/sh -# brew install asciidoctor +brew install asciidoctor -# brew install openssl@1.1 -# cp /usr/local/opt/openssl@1.1/lib/pkgconfig/*.pc /usr/local/lib/pkgconfig/ +brew install openssl@1.1 +cp /usr/local/opt/openssl@1.1/lib/pkgconfig/*.pc /usr/local/lib/pkgconfig/ diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 382be60..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,10 +0,0 @@ -# Please see the documentation for all configuration options: -# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - -version: 2 -updates: - - package-ecosystem: "cargo" - directory: "/" - schedule: - interval: "weekly" - rebase-strategy: "disabled" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e216219..f931667 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ jobs: matrix: rust: - stable - - 1.80.0 + - 1.57.0 steps: - name: Checkout sources uses: actions/checkout@v2 @@ -39,7 +39,7 @@ jobs: matrix: rust: - stable - - 1.80.0 + - 1.57.0 steps: - name: Checkout sources uses: actions/checkout@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 39b9be6..b3917b6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,7 +61,7 @@ jobs: run: echo "${{ env.VERSION }}" > artifacts/release-version - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v1 with: name: artifacts path: artifacts @@ -75,28 +75,20 @@ jobs: RUST_BACKTRACE: 1 strategy: matrix: - build: [ linux-amd64, linux-aarch64, macos-aarch64, windows ] + build: [ linux-amd64, macos-intel, windows ] include: - build: linux-amd64 - os: ubuntu-latest + os: ubuntu-18.04 rust: stable target: x86_64-unknown-linux-musl - cross: true - - build: linux-aarch64 - os: ubuntu-latest - rust: stable - target: aarch64-unknown-linux-musl - cross: true - - build: macos-aarch64 + - build: macos-intel os: macos-latest rust: stable - target: aarch64-apple-darwin - cross: false + target: x86_64-apple-darwin - build: windows os: windows-2019 rust: stable target: x86_64-pc-windows-msvc - cross: false steps: - name: Checkout repository @@ -105,7 +97,7 @@ jobs: fetch-depth: 1 - name: Install packages (Ubuntu) - if: matrix.os == 'ubuntu-latest' + if: matrix.os == 'ubuntu-18.04' run: | .github/ci/ubuntu-install-packages - name: Install packages (macOS) @@ -121,7 +113,7 @@ jobs: target: ${{ matrix.target }} - name: Get release download URL - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v1 with: name: artifacts path: artifacts @@ -134,24 +126,17 @@ jobs: echo "release upload url: $release_upload_url" - name: Build onetun binary - shell: bash - run: | - if [ "${{ matrix.cross }}" = "true" ]; then - cargo install cross - cross build --release --target ${{ matrix.target }} - else - cargo build --release --target ${{ matrix.target }} - fi + run: cargo build --release - name: Prepare onetun binary shell: bash run: | mkdir -p ci/assets if [ "${{ matrix.build }}" = "windows" ]; then - cp "target/${{ matrix.target }}/release/onetun.exe" "ci/assets/onetun.exe" + cp "target/release/onetun.exe" "ci/assets/onetun.exe" echo "ASSET=onetun.exe" >> $GITHUB_ENV else - cp "target/${{ matrix.target }}/release/onetun" "ci/assets/onetun-${{ matrix.build }}" + cp "target/release/onetun" "ci/assets/onetun-${{ matrix.build }}" echo "ASSET=onetun-${{ matrix.build }}" >> $GITHUB_ENV fi diff --git a/.gitignore b/.gitignore index 7a1777c..0333ac1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,3 @@ .envrc *.log *.pcap -.DS_Store diff --git a/Cargo.lock b/Cargo.lock index f8e12f2..b9b7c16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,58 +1,27 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] +version = 3 [[package]] name = "aho-corasick" -version = "1.1.3" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] -[[package]] -name = "anstyle" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" - [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" [[package]] name = "async-recursion" -version = "1.1.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" dependencies = [ "proc-macro2", "quote", @@ -61,9 +30,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.87" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" +checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" dependencies = [ "proc-macro2", "quote", @@ -71,31 +40,27 @@ dependencies = [ ] [[package]] -name = "autocfg" -version = "1.4.0" +name = "atty" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "addr2line", - "cfg-if", + "hermit-abi", "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets", + "winapi", ] [[package]] -name = "base64" -version = "0.13.1" +name = "autocfg" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bitflags" @@ -103,80 +68,53 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - [[package]] name = "boringtun" -version = "0.6.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "751787b019c674b9ac353f4eaa285e6711c21badb421cd8c199bf2c83b727f29" +checksum = "bcaf3e6d388237249ec234ec6890bfc68634043f9b048011de8d0fc0025c3698" dependencies = [ - "aead", "base64", - "blake2", - "chacha20poly1305", "hex", - "hmac", "ip_network", "ip_network_table", + "jni", "libc", - "nix", "parking_lot", - "rand_core", "ring", "tracing", "untrusted 0.9.0", - "x25519-dalek", ] [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byteorder" -version = "1.5.0" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.9.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cc" -version = "1.2.2" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" -dependencies = [ - "shlex", -] +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" @@ -184,198 +122,46 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", - "zeroize", -] - [[package]] name = "clap" -version = "4.5.21" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.5.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" -dependencies = [ - "anstyle", - "clap_lex", + "bitflags", "strsim", - "terminal_size", + "textwrap", + "unicode-width", ] [[package]] -name = "clap_lex" -version = "0.7.3" +name = "combine" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" - -[[package]] -name = "cpufeatures" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "rand_core", - "typenum", -] - -[[package]] -name = "curve25519-dalek" -version = "4.0.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436ace70fc06e06f7f689d2624dc4e2f0ea666efb5aa704215f7249ae6e047a7" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "fiat-crypto", - "platforms", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "defmt" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130" -dependencies = [ - "bitflags 1.3.2", - "defmt-macros", -] - -[[package]] -name = "defmt-macros" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6" -dependencies = [ - "defmt-parser", - "proc-macro-error2", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "defmt-parser" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3" -dependencies = [ - "thiserror", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", - "subtle", + "bytes", + "memchr", ] [[package]] name = "env_logger" -version = "0.10.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ + "atty", "humantime", - "is-terminal", "log", "regex", "termcolor", ] -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "fiat-crypto" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" - [[package]] name = "futures" -version = "0.3.31" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" dependencies = [ "futures-channel", "futures-core", @@ -388,9 +174,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" dependencies = [ "futures-core", "futures-sink", @@ -398,15 +184,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" dependencies = [ "futures-core", "futures-task", @@ -415,15 +201,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" dependencies = [ "proc-macro2", "quote", @@ -432,21 +218,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ "futures-channel", "futures-core", @@ -460,63 +246,31 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", "wasi", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" - -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "hash32", - "stable_deref_trait", -] +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] [[package]] name = "hex" @@ -524,40 +278,25 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - [[package]] name = "humantime" -version = "2.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] [[package]] name = "indexmap" -version = "2.7.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ - "equivalent", + "autocfg", "hashbrown", ] -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - [[package]] name = "ip_network" version = "0.4.1" @@ -581,43 +320,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e537132deb99c0eb4b752f0346b6a836200eaaa3516dd7e5514b63930a09e5d" [[package]] -name = "is-terminal" -version = "0.4.13" +name = "jni" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.52.0", + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", ] [[package]] -name = "js-sys" -version = "0.3.74" +name = "jni-sys" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ - "once_cell", "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.170" +version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -625,9 +366,12 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] [[package]] name = "managed" @@ -637,9 +381,9 @@ checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" [[package]] name = "memchr" -version = "2.7.4" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "minimal-lexical" @@ -647,73 +391,52 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" -dependencies = [ - "adler2", -] - [[package]] name = "mio" -version = "1.0.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", + "log", "wasi", - "windows-sys 0.52.0", -] - -[[package]] -name = "nix" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "libc", + "windows-sys", ] [[package]] name = "nom" -version = "7.1.3" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ "memchr", "minimal-lexical", ] [[package]] -name = "object" -version = "0.36.5" +name = "num_cpus" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ - "memchr", + "hermit-abi", + "libc", ] [[package]] name = "once_cell" -version = "1.20.2" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "onetun" -version = "0.3.10" +version = "0.3.4" dependencies = [ "anyhow", "async-recursion", "async-trait", - "base64", "boringtun", - "bytes", "clap", "futures", "log", @@ -726,17 +449,11 @@ dependencies = [ "tracing", ] -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core", @@ -744,22 +461,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-sys", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -767,37 +484,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "platforms" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d43467300237085a4f9e864b937cf0bc012cef7740be12be1a48b10d2c8a3701" - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "pretty_env_logger" -version = "0.5.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" dependencies = [ "env_logger", "log", @@ -805,51 +502,34 @@ dependencies = [ [[package]] name = "priority-queue" -version = "2.1.1" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714c75db297bc88a63783ffc6ab9f830698a6705aa0201416931759ef4c8183d" +checksum = "815082d99af3acc75a3e67efd2a07f72e67b4e81b4344eb8ca34c6ebf3dfa9c5" dependencies = [ "autocfg", - "equivalent", "indexmap", ] -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" dependencies = [ "unicode-ident", ] [[package]] -name = "quote" -version = "1.0.37" +name = "quick-error" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -886,30 +566,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -918,9 +586,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "ring" @@ -938,109 +606,55 @@ dependencies = [ ] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" -dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "winapi-util", ] [[package]] name = "scopeguard" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "serde" -version = "1.0.215" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.215" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.13.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "smoltcp" -version = "0.12.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad095989c1533c1c266d9b1e8d70a1329dd3723c3edac6d03bbd67e7bf6f4bb" +checksum = "72165c4af59f5f19c7fb774b88b95660591b612380305b5f4503157341a9f7ee" dependencies = [ - "bitflags 1.3.2", + "bitflags", "byteorder", - "cfg-if", - "defmt", - "heapless", "log", "managed", ] [[package]] name = "socket2" -version = "0.5.8" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", - "windows-sys 0.52.0", + "winapi", ] [[package]] @@ -1049,29 +663,17 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "strsim" -version = "0.11.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "syn" -version = "2.0.90" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" dependencies = [ "proc-macro2", "quote", @@ -1080,37 +682,36 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.4.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] [[package]] -name = "terminal_size" -version = "0.4.1" +name = "textwrap" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "rustix", - "windows-sys 0.59.0", + "unicode-width", ] [[package]] name = "thiserror" -version = "2.0.3" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "0a99cb8c4b9a8ef0e7907cd3b617cc8dc04d571c4e73c8ae403d80ac160bb122" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "3a891860d3c8d66fec8e73ddb3765f90082374dbaaa833407b904a94f1a7eb43" dependencies = [ "proc-macro2", "quote", @@ -1119,25 +720,28 @@ dependencies = [ [[package]] name = "tokio" -version = "1.44.0" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9975ea0f48b5aa3972bf2d888c238182458437cc2a19374b81b25cdf1023fb3a" +checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95" dependencies = [ - "backtrace", + "autocfg", "bytes", "libc", + "memchr", "mio", + "num_cpus", + "once_cell", "pin-project-lite", "socket2", "tokio-macros", - "windows-sys 0.52.0", + "winapi", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", @@ -1146,10 +750,11 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ + "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -1158,9 +763,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" dependencies = [ "proc-macro2", "quote", @@ -1169,34 +774,24 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ "once_cell", ] -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] -name = "universal-hash" -version = "0.5.1" +name = "unicode-width" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "untrusted" @@ -1211,10 +806,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] -name = "version_check" -version = "0.9.5" +name = "walkdir" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] [[package]] name = "wasi" @@ -1224,20 +824,19 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.97" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", - "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.97" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -1250,9 +849,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.97" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1260,9 +859,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.97" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -1273,15 +872,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.97" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.74" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -1305,11 +904,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "windows-sys 0.59.0", + "winapi", ] [[package]] @@ -1320,135 +919,43 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.52.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -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_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", - "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] -[[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.52.6" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] name = "windows_i686_gnu" -version = "0.52.6" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] name = "windows_i686_msvc" -version = "0.52.6" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] name = "windows_x86_64_gnu" -version = "0.52.6" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] name = "windows_x86_64_msvc" -version = "0.52.6" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "x25519-dalek" -version = "2.0.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7fae07da688e17059d5886712c933bb0520f15eff2e09cfa18e30968f4e63a" -dependencies = [ - "curve25519-dalek", - "rand_core", - "serde", - "zeroize", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/Cargo.toml b/Cargo.toml index ffb8a64..d38288f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "onetun" -version = "0.3.10" +version = "0.3.4" edition = "2021" license = "MIT" description = "A cross-platform, user-space WireGuard port-forwarder that requires no system network configurations." @@ -11,34 +11,23 @@ repository = "https://github.com/aramperes/onetun" [dependencies] # Required dependencies (bin and lib) -boringtun = { version = "0.6.0", default-features = false } +boringtun = { version = "0.4.0", default-features = false } log = "0.4" anyhow = "1" tokio = { version = "1", features = [ "rt", "sync", "io-util", "net", "time", "fs", "macros" ] } -futures = "0.3" -rand = "0.8" +futures = "0.3.17" +rand = "0.8.4" nom = "7" -async-trait = "0.1" -priority-queue = "2.1" -smoltcp = { version = "0.12", default-features = false, features = [ - "std", - "log", - "medium-ip", - "proto-ipv4", - "proto-ipv6", - "socket-udp", - "socket-tcp", -] } -bytes = "1" -base64 = "0.13" - +async-trait = "0.1.51" +priority-queue = "1.2.0" +smoltcp = { version = "0.8.0", default-features = false, features = ["std", "log", "medium-ip", "proto-ipv4", "proto-ipv6", "socket-udp", "socket-tcp"] } # forward boringtuns tracing events to log -tracing = { version = "0.1", default-features = false, features = ["log"] } +tracing = { version = "0.1.36", default-features = false, features = ["log"] } # bin-only dependencies -clap = { version = "4.4.11", default-features = false, features = ["suggestions", "std", "env", "help", "wrap_help"], optional = true } -pretty_env_logger = { version = "0.5", optional = true } -async-recursion = "1.0" +clap = { version = "2.33", default-features = false, features = ["suggestions"], optional = true } +pretty_env_logger = { version = "0.4", optional = true } +async-recursion = "1.0.0" [features] pcap = [] diff --git a/Dockerfile b/Dockerfile index 90f851d..280ebb5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.82.0 as cargo-build +FROM rust:1.57.0 as cargo-build WORKDIR /usr/src/onetun COPY Cargo.toml Cargo.toml @@ -15,9 +15,8 @@ COPY . . RUN cargo build --release FROM debian:11-slim -RUN apt-get update \ - && apt-get install dumb-init -y \ - && rm -rf /var/lib/apt/lists/* +RUN apt-get update +RUN apt-get install dumb-init -y COPY --from=cargo-build /usr/src/onetun/target/release/onetun /usr/local/bin/onetun diff --git a/LICENSE b/LICENSE index d57c948..72d8434 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 Aram Peres +Copyright (c) 2021-2022 Aram Peres Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 58204f6..eab9f07 100644 --- a/README.md +++ b/README.md @@ -21,23 +21,23 @@ For example, ## Download -onetun is available to install from [crates.io](https://crates.io/crates/onetun) with Rust ≥1.80.0: +onetun is available to install from [crates.io](https://crates.io/crates/onetun) with Rust ≥1.57.0: ```shell cargo install onetun ``` -You can also download the binary for Windows, macOS (Apple Silicon), and Linux (amd64, arm64) from +You can also download the binary for Windows, macOS (Intel), and Linux (amd64) from the [Releases](https://github.com/aramperes/onetun/releases) page. You can also run onetun using [Docker](https://hub.docker.com/r/aramperes/onetun): ```shell -docker run --rm --name onetun --user 1000 -p 8080:8080 aramperes/onetun \ +$ docker run --rm --name onetun --user 1000 -p 8080:8080 aramperes/onetun \ 0.0.0.0:8080:192.168.4.2:8080 [...options...] ``` -You can also build onetun locally, using Rust ≥1.80.0: +You can also build onetun locally, using Rust ≥1.57.0: ```shell git clone https://github.com/aramperes/onetun && cd onetun @@ -110,7 +110,7 @@ INFO onetun > Tunneling TCP [127.0.0.1:8080]->[192.168.4.2:8080] (via [140.30.3 Which means you can now access the port locally! ```shell -curl 127.0.0.1:8080 +$ curl 127.0.0.1:8080 Hello world! ``` @@ -119,31 +119,23 @@ Hello world! **onetun** supports running multiple tunnels in parallel. For example: ```shell -onetun 127.0.0.1:8080:192.168.4.2:8080 127.0.0.1:8081:192.168.4.4:8081 +$ onetun 127.0.0.1:8080:192.168.4.2:8080 127.0.0.1:8081:192.168.4.4:8081 INFO onetun::tunnel > Tunneling TCP [127.0.0.1:8080]->[192.168.4.2:8080] (via [140.30.3.182:51820] as peer 192.168.4.3) INFO onetun::tunnel > Tunneling TCP [127.0.0.1:8081]->[192.168.4.4:8081] (via [140.30.3.182:51820] as peer 192.168.4.3) ``` ... would open TCP ports 8080 and 8081 locally, which forward to their respective ports on the different peers. -#### Maximum number of tunnels - -`smoltcp` imposes a compile-time limit on the number of IP addresses assigned to an interface. **onetun** increases -the default value to support most use-cases. In effect, the default limit on the number of **onetun** peers -is **7 per protocol** (TCP and UDP). - -Should you need more unique IP addresses to forward ports to, you can increase the limit in `.cargo/config.toml` and recompile **onetun**. - ### UDP Support **onetun** supports UDP forwarding. You can add `:UDP` at the end of the port-forward configuration, or `UDP,TCP` to support both protocols on the same port (note that this opens 2 separate tunnels, just on the same port) ```shell -onetun 127.0.0.1:8080:192.168.4.2:8080:UDP +$ onetun 127.0.0.1:8080:192.168.4.2:8080:UDP INFO onetun::tunnel > Tunneling UDP [127.0.0.1:8080]->[192.168.4.2:8080] (via [140.30.3.182:51820] as peer 192.168.4.3) -onetun 127.0.0.1:8080:192.168.4.2:8080:UDP,TCP +$ onetun 127.0.0.1:8080:192.168.4.2:8080:UDP,TCP INFO onetun::tunnel > Tunneling UDP [127.0.0.1:8080]->[192.168.4.2:8080] (via [140.30.3.182:51820] as peer 192.168.4.3) INFO onetun::tunnel > Tunneling TCP [127.0.0.1:8080]->[192.168.4.2:8080] (via [140.30.3.182:51820] as peer 192.168.4.3) ``` @@ -156,7 +148,7 @@ it in any production capacity. **onetun** supports both IPv4 and IPv6. In fact, you can use onetun to forward some IP version to another, e.g. 6-to-4: ```shell -onetun [::1]:8080:192.168.4.2:8080 +$ onetun [::1]:8080:192.168.4.2:8080 INFO onetun::tunnel > Tunneling TCP [[::1]:8080]->[192.168.4.2:8080] (via [140.30.3.182:51820] as peer 192.168.4.3) ``` @@ -164,7 +156,7 @@ Note that each tunnel can only support one "source" IP version and one "destinat both IPv4 and IPv6 on the same port, you should create a second port-forward: ```shell -onetun [::1]:8080:192.168.4.2:8080 127.0.0.1:8080:192.168.4.2:8080 +$ onetun [::1]:8080:192.168.4.2:8080 127.0.0.1:8080:192.168.4.2:8080 INFO onetun::tunnel > Tunneling TCP [[::1]:8080]->[192.168.4.2:8080] (via [140.30.3.182:51820] as peer 192.168.4.3) INFO onetun::tunnel > Tunneling TCP [127.0.0.1:8080]->[192.168.4.2:8080] (via [140.30.3.182:51820] as peer 192.168.4.3) ``` @@ -175,7 +167,7 @@ For debugging purposes, you can enable the capture of IP packets sent between on The output is a libpcap capture file that can be viewed with Wireshark. ```shell -onetun --pcap wg.pcap 127.0.0.1:8080:192.168.4.2:8080 +$ onetun --pcap wg.pcap 127.0.0.1:8080:192.168.4.2:8080 INFO onetun::pcap > Capturing WireGuard IP packets to wg.pcap INFO onetun::tunnel > Tunneling TCP [127.0.0.1:8080]->[192.168.4.2:8080] (via [140.30.3.182:51820] as peer 192.168.4.3) ``` @@ -196,13 +188,6 @@ You can bind to a static address instead using `--endpoint-bind-addr`: onetun --endpoint-bind-addr 0.0.0.0:51820 --endpoint-addr 140.30.3.182:51820 [...] ``` -The security of the WireGuard connection can be further enhanced with a **pre-shared key** (PSK). You can generate such a key with the `wg genpsk` command, and provide it using `--preshared-key`. -The peer must also have this key configured using the `PresharedKey` option. - -```shell -onetun --preshared-key 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' [...] -``` - ## Architecture **In short:** onetun uses [smoltcp's](https://github.com/smoltcp-rs/smoltcp) TCP/IP and UDP stack to generate IP packets @@ -267,56 +252,6 @@ if the least recently used port hasn't been used for a certain amount of time. I All in all, I would not recommend using UDP forwarding for public services, since it's most likely prone to simple DoS or DDoS. -## HTTP/SOCKS Proxy - -**onetun** is a Transport-layer proxy (also known as port forwarding); it is not in scope to provide -a HTTP/SOCKS proxy server. However, you can easily chain **onetun** with a proxy server on a remote -that is locked down to your WireGuard network. - -For example, you could run [dante-server](https://www.inet.no/dante/) on a peer (ex. `192.168.4.2`) with the following configuration: - -``` -# /etc/danted.conf - -logoutput: syslog -user.privileged: root -user.unprivileged: nobody - -internal: 192.168.4.2 port=1080 -external: eth0 - -socksmethod: none -clientmethod: none - -# Locks down proxy use to WireGuard peers (192.168.4.x) -client pass { - from: 192.168.4.0/24 to: 0.0.0.0/0 -} -socks pass { - from: 192.168.4.0/24 to: 0.0.0.0/0 -} -``` - -Then use **onetun** to expose the SOCKS5 proxy locally: - -```shell -onetun 127.0.0.1:1080:192.168.4.2:1080 -INFO onetun::tunnel > Tunneling TCP [127.0.0.1:1080]->[192.168.4.2:1080] (via [140.30.3.182:51820] as peer 192.168.4.3) -``` - -Test with `curl` (or configure your browser): - -```shell -curl -x socks5://127.0.0.1:1080 https://ifconfig.me -``` - -## Contributing and Maintenance - -I will gladly accept contributions to onetun, and set aside time to review all pull-requests. -Please consider opening a GitHub issue if you are unsure if your contribution is within the scope of the project. - -**Disclaimer**: I do not have enough personal time to actively maintain onetun besides open-source contributions. - ## License -MIT License. See `LICENSE` for details. Copyright © 2025 Aram Peres. +MIT License. See `LICENSE` for details. Copyright © 2021-2022 Aram Peres. diff --git a/src/config.rs b/src/config.rs index 411efa3..9d9732d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -5,19 +5,18 @@ use std::fs::read_to_string; use std::net::{IpAddr, SocketAddr, ToSocketAddrs}; use std::sync::Arc; -use anyhow::{bail, Context}; -pub use boringtun::x25519::{PublicKey, StaticSecret}; +use anyhow::Context; +pub use boringtun::crypto::{X25519PublicKey, X25519SecretKey}; const DEFAULT_PORT_FORWARD_SOURCE: &str = "127.0.0.1"; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Config { pub port_forwards: Vec, #[allow(dead_code)] pub remote_port_forwards: Vec, - pub private_key: Arc, - pub endpoint_public_key: Arc, - pub preshared_key: Option<[u8; 32]>, + pub private_key: Arc, + pub endpoint_public_key: Arc, pub endpoint_addr: SocketAddr, pub endpoint_bind_addr: SocketAddr, pub source_peer_ip: IpAddr, @@ -31,17 +30,18 @@ pub struct Config { impl Config { #[cfg(feature = "bin")] pub fn from_args() -> anyhow::Result { - use clap::{Arg, Command}; + use clap::{App, Arg}; let mut warnings = vec![]; - let matches = Command::new("onetun") + let matches = App::new("onetun") .author("Aram Peres ") .version(env!("CARGO_PKG_VERSION")) .args(&[ - Arg::new("PORT_FORWARD") + Arg::with_name("PORT_FORWARD") .required(false) - .num_args(1..) + .multiple(true) + .takes_value(true) .help("Port forward configurations. The format of each argument is [src_host:]::[:TCP,UDP,...], \ where [src_host] is the local IP to listen on, is the local port to listen on, is the remote peer IP to forward to, and is the remote port to forward to. \ Environment variables of the form 'ONETUN_PORT_FORWARD_[#]' are also accepted, where [#] starts at 1.\n\ @@ -55,79 +55,74 @@ impl Config { \tlocalhost:8080:192.168.4.1:8081:TCP\n\ \tlocalhost:8080:peer.intranet:8081:TCP\ "), - Arg::new("private-key") - .conflicts_with("private-key-file") - .num_args(1) + Arg::with_name("private-key") + .required_unless("private-key-file") + .takes_value(true) .long("private-key") .env("ONETUN_PRIVATE_KEY") .help("The private key of this peer. The corresponding public key should be registered in the WireGuard endpoint. \ You can also use '--private-key-file' to specify a file containing the key instead."), - Arg::new("private-key-file") - .num_args(1) + Arg::with_name("private-key-file") + .takes_value(true) .long("private-key-file") .env("ONETUN_PRIVATE_KEY_FILE") .help("The path to a file containing the private key of this peer. The corresponding public key should be registered in the WireGuard endpoint."), - Arg::new("endpoint-public-key") + Arg::with_name("endpoint-public-key") .required(true) - .num_args(1) + .takes_value(true) .long("endpoint-public-key") .env("ONETUN_ENDPOINT_PUBLIC_KEY") .help("The public key of the WireGuard endpoint (remote)."), - Arg::new("preshared-key") - .required(false) - .num_args(1) - .long("preshared-key") - .env("ONETUN_PRESHARED_KEY") - .help("The pre-shared key (PSK) as configured with the peer."), - Arg::new("endpoint-addr") + Arg::with_name("endpoint-addr") .required(true) - .num_args(1) + .takes_value(true) .long("endpoint-addr") .env("ONETUN_ENDPOINT_ADDR") .help("The address (IP + port) of the WireGuard endpoint (remote). Example: 1.2.3.4:51820"), - Arg::new("endpoint-bind-addr") + Arg::with_name("endpoint-bind-addr") .required(false) - .num_args(1) + .takes_value(true) .long("endpoint-bind-addr") .env("ONETUN_ENDPOINT_BIND_ADDR") .help("The address (IP + port) used to bind the local UDP socket for the WireGuard tunnel. Example: 1.2.3.4:30000. Defaults to 0.0.0.0:0 for IPv4 endpoints, or [::]:0 for IPv6 endpoints."), - Arg::new("source-peer-ip") + Arg::with_name("source-peer-ip") .required(true) - .num_args(1) + .takes_value(true) .long("source-peer-ip") .env("ONETUN_SOURCE_PEER_IP") .help("The source IP to identify this peer as (local). Example: 192.168.4.3"), - Arg::new("keep-alive") + Arg::with_name("keep-alive") .required(false) - .num_args(1) + .takes_value(true) .long("keep-alive") .env("ONETUN_KEEP_ALIVE") .help("Configures a persistent keep-alive for the WireGuard tunnel, in seconds."), - Arg::new("max-transmission-unit") + Arg::with_name("max-transmission-unit") .required(false) - .num_args(1) + .takes_value(true) .long("max-transmission-unit") .env("ONETUN_MTU") .default_value("1420") .help("Configures the max-transmission-unit (MTU) of the WireGuard tunnel."), - Arg::new("log") + Arg::with_name("log") .required(false) - .num_args(1) + .takes_value(true) .long("log") .env("ONETUN_LOG") .default_value("info") .help("Configures the log level and format."), - Arg::new("pcap") + Arg::with_name("pcap") .required(false) - .num_args(1) + .takes_value(true) .long("pcap") .env("ONETUN_PCAP") .help("Decrypts and captures IP packets on the WireGuard tunnel to a given output file."), - Arg::new("remote") + Arg::with_name("remote") .required(false) - .num_args(1..) + .takes_value(true) + .multiple(true) .long("remote") - .short('r') + .short("r") .help("Remote port forward configurations. The format of each argument is ::[:TCP,UDP,...], \ where is the port the other peers will reach the server with, is the IP to forward to, and is the port to forward to. \ The will be bound on onetun's peer IP, as specified by --source-peer-ip. If you pass a different value for here, it will be rejected.\n\ @@ -142,7 +137,7 @@ impl Config { // Combine `PORT_FORWARD` arg and `ONETUN_PORT_FORWARD_#` envs let mut port_forward_strings = HashSet::new(); - if let Some(values) = matches.get_many::("PORT_FORWARD") { + if let Some(values) = matches.values_of("PORT_FORWARD") { for value in values { port_forward_strings.insert(value.to_owned()); } @@ -161,18 +156,18 @@ impl Config { .map(|s| PortForwardConfig::from_notation(&s, DEFAULT_PORT_FORWARD_SOURCE)) .collect(); let port_forwards: Vec = port_forwards - .context("Failed to parse port forward config")? + .with_context(|| "Failed to parse port forward config")? .into_iter() .flatten() .collect(); // Read source-peer-ip - let source_peer_ip = parse_ip(matches.get_one::("source-peer-ip")) - .context("Invalid source peer IP")?; + let source_peer_ip = parse_ip(matches.value_of("source-peer-ip")) + .with_context(|| "Invalid source peer IP")?; // Combined `remote` arg and `ONETUN_REMOTE_PORT_FORWARD_#` envs let mut port_forward_strings = HashSet::new(); - if let Some(values) = matches.get_many::("remote") { + if let Some(values) = matches.values_of("remote") { for value in values { port_forward_strings.insert(value.to_owned()); } @@ -191,30 +186,30 @@ impl Config { .map(|s| { PortForwardConfig::from_notation( &s, - matches.get_one::("source-peer-ip").unwrap(), + matches.value_of("source-peer-ip").unwrap(), ) }) .collect(); let mut remote_port_forwards: Vec = remote_port_forwards - .context("Failed to parse remote port forward config")? + .with_context(|| "Failed to parse remote port forward config")? .into_iter() .flatten() .collect(); for port_forward in remote_port_forwards.iter_mut() { if port_forward.source.ip() != source_peer_ip { - bail!("Remote port forward config must match --source-peer-ip ({}), or be omitted.", source_peer_ip); + return Err(anyhow::anyhow!("Remote port forward config must match --source-peer-ip ({}), or be omitted.", source_peer_ip)); } port_forward.source = SocketAddr::from((source_peer_ip, port_forward.source.port())); port_forward.remote = true; } if port_forwards.is_empty() && remote_port_forwards.is_empty() { - bail!("No port forward configurations given."); + return Err(anyhow::anyhow!("No port forward configurations given.")); } // Read private key from file or CLI argument let (group_readable, world_readable) = matches - .get_one::("private-key-file") + .value_of("private-key-file") .and_then(is_file_insecurely_readable) .unwrap_or_default(); if group_readable { @@ -224,32 +219,31 @@ impl Config { warnings.push("Private key file is world-readable. This is insecure.".into()); } - let private_key = if let Some(private_key_file) = - matches.get_one::("private-key-file") - { + let private_key = if let Some(private_key_file) = matches.value_of("private-key-file") { read_to_string(private_key_file) .map(|s| s.trim().to_string()) - .context("Failed to read private key file") + .with_context(|| "Failed to read private key file") } else { if std::env::var("ONETUN_PRIVATE_KEY").is_err() { warnings.push("Private key was passed using CLI. This is insecure. \ Use \"--private-key-file \", or the \"ONETUN_PRIVATE_KEY\" env variable instead.".into()); } matches - .get_one::("private-key") - .cloned() - .context("Missing private key") + .value_of("private-key") + .map(String::from) + .with_context(|| "Missing private key") }?; - let endpoint_addr = parse_addr(matches.get_one::("endpoint-addr")) - .context("Invalid endpoint address")?; + let endpoint_addr = parse_addr(matches.value_of("endpoint-addr")) + .with_context(|| "Invalid endpoint address")?; - let endpoint_bind_addr = if let Some(addr) = matches.get_one::("endpoint-bind-addr") - { - let addr = parse_addr(Some(addr)).context("Invalid bind address")?; + let endpoint_bind_addr = if let Some(addr) = matches.value_of("endpoint-bind-addr") { + let addr = parse_addr(Some(addr)).with_context(|| "Invalid bind address")?; // Make sure the bind address and endpoint address are the same IP version if addr.ip().is_ipv4() != endpoint_addr.ip().is_ipv4() { - bail!("Endpoint and bind addresses must be the same IP version"); + return Err(anyhow::anyhow!( + "Endpoint and bind addresses must be the same IP version" + )); } addr } else { @@ -263,77 +257,54 @@ impl Config { Ok(Self { port_forwards, remote_port_forwards, - private_key: Arc::new(parse_private_key(&private_key).context("Invalid private key")?), - endpoint_public_key: Arc::new( - parse_public_key(matches.get_one::("endpoint-public-key")) - .context("Invalid endpoint public key")?, + private_key: Arc::new( + parse_private_key(&private_key).with_context(|| "Invalid private key")?, + ), + endpoint_public_key: Arc::new( + parse_public_key(matches.value_of("endpoint-public-key")) + .with_context(|| "Invalid endpoint public key")?, ), - preshared_key: parse_preshared_key(matches.get_one::("preshared-key"))?, endpoint_addr, endpoint_bind_addr, source_peer_ip, - keepalive_seconds: parse_keep_alive(matches.get_one::("keep-alive")) - .context("Invalid keep-alive value")?, - max_transmission_unit: parse_mtu(matches.get_one::("max-transmission-unit")) - .context("Invalid max-transmission-unit value")?, - log: matches - .get_one::("log") - .cloned() - .unwrap_or_default(), - pcap_file: matches.get_one::("pcap").cloned(), + keepalive_seconds: parse_keep_alive(matches.value_of("keep-alive")) + .with_context(|| "Invalid keep-alive value")?, + max_transmission_unit: parse_mtu(matches.value_of("max-transmission-unit")) + .with_context(|| "Invalid max-transmission-unit value")?, + log: matches.value_of("log").unwrap_or_default().into(), + pcap_file: matches.value_of("pcap").map(String::from), warnings, }) } } -fn parse_addr>(s: Option) -> anyhow::Result { - s.context("Missing address")? - .as_ref() +fn parse_addr(s: Option<&str>) -> anyhow::Result { + s.with_context(|| "Missing address")? .to_socket_addrs() - .context("Invalid address")? + .with_context(|| "Invalid address")? .next() - .context("Could not lookup address") + .with_context(|| "Could not lookup address") } -fn parse_ip(s: Option<&String>) -> anyhow::Result { - s.context("Missing IP address")? +fn parse_ip(s: Option<&str>) -> anyhow::Result { + s.with_context(|| "Missing IP")? .parse::() - .context("Invalid IP address") + .with_context(|| "Invalid IP address") } -fn parse_private_key(s: &str) -> anyhow::Result { - let decoded = base64::decode(s).context("Failed to decode private key")?; - if let Ok::<[u8; 32], _>(bytes) = decoded.try_into() { - Ok(StaticSecret::from(bytes)) - } else { - bail!("Invalid private key") - } +fn parse_private_key(s: &str) -> anyhow::Result { + s.parse::() + .map_err(|e| anyhow::anyhow!("{}", e)) } -fn parse_public_key(s: Option<&String>) -> anyhow::Result { - let encoded = s.context("Missing public key")?; - let decoded = base64::decode(encoded).context("Failed to decode public key")?; - if let Ok::<[u8; 32], _>(bytes) = decoded.try_into() { - Ok(PublicKey::from(bytes)) - } else { - bail!("Invalid public key") - } +fn parse_public_key(s: Option<&str>) -> anyhow::Result { + s.with_context(|| "Missing public key")? + .parse::() + .map_err(|e| anyhow::anyhow!("{}", e)) + .with_context(|| "Invalid public key") } -fn parse_preshared_key(s: Option<&String>) -> anyhow::Result> { - if let Some(s) = s { - let decoded = base64::decode(s).context("Failed to decode preshared key")?; - if let Ok::<[u8; 32], _>(bytes) = decoded.try_into() { - Ok(Some(bytes)) - } else { - bail!("Invalid preshared key") - } - } else { - Ok(None) - } -} - -fn parse_keep_alive(s: Option<&String>) -> anyhow::Result> { +fn parse_keep_alive(s: Option<&str>) -> anyhow::Result> { if let Some(s) = s { let parsed: u16 = s.parse().with_context(|| { format!( @@ -347,21 +318,23 @@ fn parse_keep_alive(s: Option<&String>) -> anyhow::Result> { } } -fn parse_mtu(s: Option<&String>) -> anyhow::Result { - s.context("Missing MTU")?.parse().context("Invalid MTU") +fn parse_mtu(s: Option<&str>) -> anyhow::Result { + s.with_context(|| "Missing MTU")? + .parse() + .with_context(|| "Invalid MTU") } #[cfg(unix)] -fn is_file_insecurely_readable(path: &String) -> Option<(bool, bool)> { +fn is_file_insecurely_readable(path: &str) -> Option<(bool, bool)> { use std::fs::File; use std::os::unix::fs::MetadataExt; - let mode = File::open(path).ok()?.metadata().ok()?.mode(); + let mode = File::open(&path).ok()?.metadata().ok()?.mode(); Some((mode & 0o40 > 0, mode & 0o4 > 0)) } #[cfg(not(unix))] -fn is_file_insecurely_readable(_path: &String) -> Option<(bool, bool)> { +fn is_file_insecurely_readable(_path: &str) -> Option<(bool, bool)> { // No good way to determine permissions on non-Unix target None } @@ -477,21 +450,27 @@ impl PortForwardConfig { let source = ( src_addr.0.unwrap_or(default_source), - src_addr.1.parse::().context("Invalid source port")?, + src_addr + .1 + .parse::() + .with_context(|| "Invalid source port")?, ) .to_socket_addrs() - .context("Invalid source address")? + .with_context(|| "Invalid source address")? .next() - .context("Could not resolve source address")?; + .with_context(|| "Could not resolve source address")?; let destination = ( dst_addr.0, - dst_addr.1.parse::().context("Invalid source port")?, + dst_addr + .1 + .parse::() + .with_context(|| "Invalid source port")?, ) .to_socket_addrs() // TODO: Pass this as given and use DNS config instead (issue #15) - .context("Invalid destination address")? + .with_context(|| "Invalid destination address")? .next() - .context("Could not resolve destination address")?; + .with_context(|| "Could not resolve destination address")?; // Parse protocols let protocols = if let Some(protocols) = protocols { @@ -501,7 +480,7 @@ impl PortForwardConfig { } else { Ok(vec![PortProtocol::Tcp]) } - .context("Failed to parse protocols")?; + .with_context(|| "Failed to parse protocols")?; // Returns an config for each protocol Ok(protocols diff --git a/src/events.rs b/src/events.rs index d6582ce..cd76a49 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,4 +1,3 @@ -use bytes::Bytes; use std::fmt::{Display, Formatter}; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; @@ -17,13 +16,13 @@ pub enum Event { /// A connection was dropped from the pool and should be closed in all interfaces. ClientConnectionDropped(VirtualPort), /// Data received by the local server that should be sent to the virtual server. - LocalData(PortForwardConfig, VirtualPort, Bytes), + LocalData(PortForwardConfig, VirtualPort, Vec), /// Data received by the remote server that should be sent to the local client. - RemoteData(VirtualPort, Bytes), + RemoteData(VirtualPort, Vec), /// IP packet received from the WireGuard tunnel that should be passed through the corresponding virtual device. - InboundInternetPacket(PortProtocol, Bytes), + InboundInternetPacket(PortProtocol, Vec), /// IP packet to be sent through the WireGuard tunnel as crafted by the virtual device. - OutboundInternetPacket(Bytes), + OutboundInternetPacket(Vec), /// Notifies that a virtual device read an IP packet. VirtualDeviceFed(PortProtocol), } diff --git a/src/lib.rs b/src/lib.rs index a76fa18..a43d657 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,7 +41,7 @@ pub async fn start_tunnels(config: Config, bus: Bus) -> anyhow::Result<()> { let wg = WireGuardTunnel::new(&config, bus.clone()) .await - .context("Failed to initialize WireGuard tunnel")?; + .with_context(|| "Failed to initialize WireGuard tunnel")?; let wg = Arc::new(wg); { diff --git a/src/main.rs b/src/main.rs index 4ff2954..78c6419 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ async fn main() -> anyhow::Result<()> { use anyhow::Context; use onetun::{config::Config, events::Bus}; - let config = Config::from_args().context("Configuration has errors")?; + let config = Config::from_args().with_context(|| "Failed to read config")?; init_logger(&config)?; for warning in &config.warnings { @@ -32,5 +32,7 @@ fn init_logger(config: &onetun::config::Config) -> anyhow::Result<()> { let mut builder = pretty_env_logger::formatted_timed_builder(); builder.parse_filters(&config.log); - builder.try_init().context("Failed to initialize logger") + builder + .try_init() + .with_context(|| "Failed to initialize logger") } diff --git a/src/pcap.rs b/src/pcap.rs index 487fbe0..1771a33 100644 --- a/src/pcap.rs +++ b/src/pcap.rs @@ -16,7 +16,7 @@ impl Pcap { self.writer .flush() .await - .context("Failed to flush pcap writer") + .with_context(|| "Failed to flush pcap writer") } async fn write(&mut self, data: &[u8]) -> anyhow::Result { @@ -30,14 +30,14 @@ impl Pcap { self.writer .write_u16(value) .await - .context("Failed to write u16 to pcap writer") + .with_context(|| "Failed to write u16 to pcap writer") } async fn write_u32(&mut self, value: u32) -> anyhow::Result<()> { self.writer .write_u32(value) .await - .context("Failed to write u32 to pcap writer") + .with_context(|| "Failed to write u32 to pcap writer") } async fn global_header(&mut self) -> anyhow::Result<()> { @@ -64,14 +64,14 @@ impl Pcap { async fn packet(&mut self, timestamp: Instant, packet: &[u8]) -> anyhow::Result<()> { self.packet_header(timestamp, packet.len()) .await - .context("Failed to write packet header to pcap writer")?; + .with_context(|| "Failed to write packet header to pcap writer")?; self.write(packet) .await - .context("Failed to write packet to pcap writer")?; + .with_context(|| "Failed to write packet to pcap writer")?; self.writer .flush() .await - .context("Failed to flush pcap writer")?; + .with_context(|| "Failed to flush pcap writer")?; self.flush().await } } @@ -81,14 +81,14 @@ pub async fn capture(pcap_file: String, bus: Bus) -> anyhow::Result<()> { let mut endpoint = bus.new_endpoint(); let file = File::create(&pcap_file) .await - .context("Failed to create pcap file")?; + .with_context(|| "Failed to create pcap file")?; let writer = BufWriter::new(file); let mut writer = Pcap { writer }; writer .global_header() .await - .context("Failed to write global header to pcap writer")?; + .with_context(|| "Failed to write global header to pcap writer")?; info!("Capturing WireGuard IP packets to {}", &pcap_file); loop { @@ -98,14 +98,14 @@ pub async fn capture(pcap_file: String, bus: Bus) -> anyhow::Result<()> { writer .packet(instant, &ip) .await - .context("Failed to write inbound IP packet to pcap writer")?; + .with_context(|| "Failed to write inbound IP packet to pcap writer")?; } Event::OutboundInternetPacket(ip) => { let instant = Instant::now(); writer .packet(instant, &ip) .await - .context("Failed to write output IP packet to pcap writer")?; + .with_context(|| "Failed to write output IP packet to pcap writer")?; } _ => {} } diff --git a/src/tunnel/tcp.rs b/src/tunnel/tcp.rs index 47b0197..557f5ad 100644 --- a/src/tunnel/tcp.rs +++ b/src/tunnel/tcp.rs @@ -1,18 +1,17 @@ +use crate::config::{PortForwardConfig, PortProtocol}; +use crate::virtual_iface::VirtualPort; +use anyhow::Context; use std::collections::VecDeque; -use std::ops::Range; use std::sync::Arc; +use tokio::net::{TcpListener, TcpStream}; + +use std::ops::Range; use std::time::Duration; -use anyhow::Context; -use bytes::BytesMut; +use crate::events::{Bus, Event}; use rand::seq::SliceRandom; use rand::thread_rng; use tokio::io::AsyncWriteExt; -use tokio::net::{TcpListener, TcpStream}; - -use crate::config::{PortForwardConfig, PortProtocol}; -use crate::events::{Bus, Event}; -use crate::virtual_iface::VirtualPort; const MAX_PACKET: usize = 65536; const MIN_PORT: u16 = 1000; @@ -27,14 +26,14 @@ pub async fn tcp_proxy_server( ) -> anyhow::Result<()> { let listener = TcpListener::bind(port_forward.source) .await - .context("Failed to listen on TCP proxy server")?; + .with_context(|| "Failed to listen on TCP proxy server")?; loop { let port_pool = port_pool.clone(); let (socket, peer_addr) = listener .accept() .await - .context("Failed to accept connection on TCP proxy server")?; + .with_context(|| "Failed to accept connection on TCP proxy server")?; // Assign a 'virtual port': this is a unique port number used to route IP packets // received from the WireGuard tunnel. It is the port number that the virtual client will @@ -82,7 +81,7 @@ async fn handle_tcp_proxy_connection( let mut endpoint = bus.new_endpoint(); endpoint.send(Event::ClientConnectionInitiated(port_forward, virtual_port)); - let mut buffer = BytesMut::with_capacity(MAX_PACKET); + let mut buffer = Vec::with_capacity(MAX_PACKET); loop { tokio::select! { readable_result = socket.readable() => { @@ -91,7 +90,7 @@ async fn handle_tcp_proxy_connection( match socket.try_read_buf(&mut buffer) { Ok(size) if size > 0 => { let data = Vec::from(&buffer[..size]); - endpoint.send(Event::LocalData(port_forward, virtual_port, data.into())); + endpoint.send(Event::LocalData(port_forward, virtual_port, data)); // Reset buffer buffer.clear(); } @@ -192,7 +191,7 @@ impl TcpPortPool { let port = inner .queue .pop_front() - .context("TCP virtual port pool is exhausted")?; + .with_context(|| "TCP virtual port pool is exhausted")?; Ok(VirtualPort::new(port, PortProtocol::Tcp)) } diff --git a/src/tunnel/udp.rs b/src/tunnel/udp.rs index ab52dc7..1d25914 100644 --- a/src/tunnel/udp.rs +++ b/src/tunnel/udp.rs @@ -4,15 +4,14 @@ use std::ops::Range; use std::sync::Arc; use std::time::Instant; +use crate::events::{Bus, Event}; use anyhow::Context; -use bytes::Bytes; use priority_queue::double_priority_queue::DoublePriorityQueue; use rand::seq::SliceRandom; use rand::thread_rng; use tokio::net::UdpSocket; use crate::config::{PortForwardConfig, PortProtocol}; -use crate::events::{Bus, Event}; use crate::virtual_iface::VirtualPort; const MAX_PACKET: usize = 65536; @@ -37,7 +36,7 @@ pub async fn udp_proxy_server( let mut endpoint = bus.new_endpoint(); let socket = UdpSocket::bind(port_forward.source) .await - .context("Failed to bind on UDP proxy address")?; + .with_context(|| "Failed to bind on UDP proxy address")?; let mut buffer = [0u8; MAX_PACKET]; loop { @@ -99,11 +98,11 @@ async fn next_udp_datagram( socket: &UdpSocket, buffer: &mut [u8], port_pool: UdpPortPool, -) -> anyhow::Result> { +) -> anyhow::Result)>> { let (size, peer_addr) = socket .recv_from(buffer) .await - .context("Failed to accept incoming UDP datagram")?; + .with_context(|| "Failed to accept incoming UDP datagram")?; // Assign a 'virtual port': this is a unique port number used to route IP packets // received from the WireGuard tunnel. It is the port number that the virtual client will @@ -127,7 +126,7 @@ async fn next_udp_datagram( port_pool.update_last_transmit(port).await; let data = buffer[..size].to_vec(); - Ok(Some((port, data.into()))) + Ok(Some((port, data))) } /// A pool of virtual ports available for TCP connections. @@ -212,7 +211,7 @@ impl UdpPortPool { None } }) - .context("Virtual port pool is exhausted")?; + .with_context(|| "virtual port pool is exhausted")?; inner.port_by_peer_addr.insert(peer_addr, port); inner.peer_addr_by_port.insert(port, peer_addr); diff --git a/src/virtual_device.rs b/src/virtual_device.rs index 28d8751..e0e7e4d 100644 --- a/src/virtual_device.rs +++ b/src/virtual_device.rs @@ -1,15 +1,10 @@ use crate::config::PortProtocol; use crate::events::{BusSender, Event}; use crate::Bus; -use bytes::{BufMut, Bytes, BytesMut}; -use smoltcp::{ - phy::{DeviceCapabilities, Medium}, - time::Instant, -}; -use std::{ - collections::VecDeque, - sync::{Arc, Mutex}, -}; +use smoltcp::phy::{Device, DeviceCapabilities, Medium}; +use smoltcp::time::Instant; +use std::collections::VecDeque; +use std::sync::{Arc, Mutex}; /// A virtual device that processes IP packets through smoltcp and WireGuard. pub struct VirtualIpDevice { @@ -18,7 +13,7 @@ pub struct VirtualIpDevice { /// Channel receiver for received IP packets. bus_sender: BusSender, /// Local queue for packets received from the bus that need to go through the smoltcp interface. - process_queue: Arc>>, + process_queue: Arc>>>, } impl VirtualIpDevice { @@ -54,17 +49,11 @@ impl VirtualIpDevice { } } -impl smoltcp::phy::Device for VirtualIpDevice { - type RxToken<'a> - = RxToken - where - Self: 'a; - type TxToken<'a> - = TxToken - where - Self: 'a; +impl<'a> Device<'a> for VirtualIpDevice { + type RxToken = RxToken; + type TxToken = TxToken; - fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { + fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { let next = { let mut queue = self .process_queue @@ -74,13 +63,7 @@ impl smoltcp::phy::Device for VirtualIpDevice { }; match next { Some(buffer) => Some(( - Self::RxToken { - buffer: { - let mut buf = BytesMut::new(); - buf.put(buffer); - buf - }, - }, + Self::RxToken { buffer }, Self::TxToken { sender: self.bus_sender.clone(), }, @@ -89,7 +72,7 @@ impl smoltcp::phy::Device for VirtualIpDevice { } } - fn transmit(&mut self, _timestamp: Instant) -> Option> { + fn transmit(&'a mut self) -> Option { Some(TxToken { sender: self.bus_sender.clone(), }) @@ -105,15 +88,15 @@ impl smoltcp::phy::Device for VirtualIpDevice { #[doc(hidden)] pub struct RxToken { - buffer: BytesMut, + buffer: Vec, } impl smoltcp::phy::RxToken for RxToken { - fn consume(self, f: F) -> R + fn consume(mut self, _timestamp: Instant, f: F) -> smoltcp::Result where - F: FnOnce(&[u8]) -> R, + F: FnOnce(&mut [u8]) -> smoltcp::Result, { - f(&self.buffer) + f(&mut self.buffer) } } @@ -123,14 +106,14 @@ pub struct TxToken { } impl smoltcp::phy::TxToken for TxToken { - fn consume(self, len: usize, f: F) -> R + fn consume(self, _timestamp: Instant, len: usize, f: F) -> smoltcp::Result where - F: FnOnce(&mut [u8]) -> R, + F: FnOnce(&mut [u8]) -> smoltcp::Result, { - let mut buffer = vec![0; len]; + let mut buffer = Vec::new(); + buffer.resize(len, 0); let result = f(&mut buffer); - self.sender - .send(Event::OutboundInternetPacket(buffer.into())); + self.sender.send(Event::OutboundInternetPacket(buffer)); result } } diff --git a/src/virtual_iface/tcp.rs b/src/virtual_iface/tcp.rs index 3a3fd8d..28eacac 100644 --- a/src/virtual_iface/tcp.rs +++ b/src/virtual_iface/tcp.rs @@ -5,19 +5,12 @@ use crate::virtual_iface::{VirtualInterfacePoll, VirtualPort}; use crate::Bus; use anyhow::Context; use async_trait::async_trait; -use bytes::Bytes; -use smoltcp::iface::PollResult; -use smoltcp::{ - iface::{Config, Interface, SocketHandle, SocketSet}, - socket::tcp, - time::Instant, - wire::{HardwareAddress, IpAddress, IpCidr, IpVersion}, -}; -use std::{ - collections::{HashMap, HashSet, VecDeque}, - net::IpAddr, - time::Duration, -}; +use smoltcp::iface::{InterfaceBuilder, SocketHandle}; +use smoltcp::socket::{TcpSocket, TcpSocketBuffer, TcpState}; +use smoltcp::wire::{IpAddress, IpCidr}; +use std::collections::{HashMap, HashSet, VecDeque}; +use std::net::IpAddr; +use std::time::Duration; const MAX_PACKET: usize = 65536; @@ -26,7 +19,6 @@ pub struct TcpVirtualInterface { source_peer_ip: IpAddr, port_forwards: Vec, bus: Bus, - sockets: SocketSet<'static>, } impl TcpVirtualInterface { @@ -40,34 +32,33 @@ impl TcpVirtualInterface { .collect(), source_peer_ip, bus, - sockets: SocketSet::new([]), } } - fn new_server_socket(port_forward: PortForwardConfig) -> anyhow::Result> { + fn new_server_socket(port_forward: PortForwardConfig) -> anyhow::Result> { static mut TCP_SERVER_RX_DATA: [u8; 0] = []; static mut TCP_SERVER_TX_DATA: [u8; 0] = []; - let tcp_rx_buffer = tcp::SocketBuffer::new(unsafe { &mut TCP_SERVER_RX_DATA[..] }); - let tcp_tx_buffer = tcp::SocketBuffer::new(unsafe { &mut TCP_SERVER_TX_DATA[..] }); - let mut socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer); + let tcp_rx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_RX_DATA[..] }); + let tcp_tx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_TX_DATA[..] }); + let mut socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer); socket .listen(( IpAddress::from(port_forward.destination.ip()), port_forward.destination.port(), )) - .context("Virtual server socket failed to listen")?; + .with_context(|| "Virtual server socket failed to listen")?; Ok(socket) } - fn new_client_socket() -> anyhow::Result> { + fn new_client_socket() -> anyhow::Result> { let rx_data = vec![0u8; MAX_PACKET]; let tx_data = vec![0u8; MAX_PACKET]; - let tcp_rx_buffer = tcp::SocketBuffer::new(rx_data); - let tcp_tx_buffer = tcp::SocketBuffer::new(tx_data); - let socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer); + let tcp_rx_buffer = TcpSocketBuffer::new(rx_data); + let tcp_tx_buffer = TcpSocketBuffer::new(tx_data); + let socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer); Ok(socket) } @@ -79,32 +70,26 @@ impl TcpVirtualInterface { } addresses .into_iter() - .map(|addr| IpCidr::new(addr, addr_length(&addr))) + .map(|addr| IpCidr::new(addr, 32)) .collect() } } #[async_trait] impl VirtualInterfacePoll for TcpVirtualInterface { - async fn poll_loop(mut self, mut device: VirtualIpDevice) -> anyhow::Result<()> { + async fn poll_loop(self, device: VirtualIpDevice) -> anyhow::Result<()> { // Create CIDR block for source peer IP + each port forward IP let addresses = self.addresses(); - let config = Config::new(HardwareAddress::Ip); // Create virtual interface (contains smoltcp state machine) - let mut iface = Interface::new(config, &mut device, Instant::now()); - iface.update_ip_addrs(|ip_addrs| { - addresses.into_iter().for_each(|addr| { - ip_addrs - .push(addr) - .expect("maximum number of IPs in TCP interface reached"); - }); - }); + let mut iface = InterfaceBuilder::new(device, vec![]) + .ip_addrs(addresses) + .finalize(); // Create virtual server for each port forward for port_forward in self.port_forwards.iter() { let server_socket = TcpVirtualInterface::new_server_socket(*port_forward)?; - self.sockets.add(server_socket); + iface.add_socket(server_socket); } // The next time to poll the interface. Can be None for instant poll. @@ -117,7 +102,7 @@ impl VirtualInterfacePoll for TcpVirtualInterface { let mut port_client_handle_map: HashMap = HashMap::new(); // Data packets to send from a virtual client - let mut send_queue: HashMap> = HashMap::new(); + let mut send_queue: HashMap>> = HashMap::new(); loop { tokio::select! { @@ -130,11 +115,11 @@ impl VirtualInterfacePoll for TcpVirtualInterface { // Find closed sockets port_client_handle_map.retain(|virtual_port, client_handle| { - let client_socket = self.sockets.get_mut::(*client_handle); - if client_socket.state() == tcp::State::Closed { + let client_socket = iface.get_socket::(*client_handle); + if client_socket.state() == TcpState::Closed { endpoint.send(Event::ClientConnectionDropped(*virtual_port)); send_queue.remove(virtual_port); - self.sockets.remove(*client_handle); + iface.remove_socket(*client_handle); false } else { // Not closed, retain @@ -142,12 +127,16 @@ impl VirtualInterfacePoll for TcpVirtualInterface { } }); - if iface.poll(loop_start, &mut device, &mut self.sockets) == PollResult::SocketStateChanged { - log::trace!("TCP virtual interface polled some packets to be processed"); + match iface.poll(loop_start) { + Ok(processed) if processed => { + trace!("TCP virtual interface polled some packets to be processed"); + } + Err(e) => error!("TCP virtual interface poll error: {:?}", e), + _ => {} } for (virtual_port, client_handle) in port_client_handle_map.iter() { - let client_socket = self.sockets.get_mut::(*client_handle); + let client_socket = iface.get_socket::(*client_handle); if client_socket.can_send() { if let Some(send_queue) = send_queue.get_mut(virtual_port) { let to_transfer = send_queue.pop_front(); @@ -158,7 +147,7 @@ impl VirtualInterfacePoll for TcpVirtualInterface { if sent < total { // Sometimes only a subset is sent, so the rest needs to be sent on the next poll let tx_extra = Vec::from(&to_transfer_slice[sent..total]); - send_queue.push_front(tx_extra.into()); + send_queue.push_front(tx_extra); } } Err(e) => { @@ -167,13 +156,13 @@ impl VirtualInterfacePoll for TcpVirtualInterface { ); } } - } else if client_socket.state() == tcp::State::CloseWait { + } else if client_socket.state() == TcpState::CloseWait { client_socket.close(); } } } if client_socket.can_recv() { - match client_socket.recv(|buffer| (buffer.len(), Bytes::from(buffer.to_vec()))) { + match client_socket.recv(|buffer| (buffer.len(), buffer.to_vec())) { Ok(data) => { debug!("[{}] Received {} bytes from virtual server", virtual_port, data.len()); if !data.is_empty() { @@ -190,7 +179,7 @@ impl VirtualInterfacePoll for TcpVirtualInterface { } // The virtual interface determines the next time to poll (this is to reduce unnecessary polls) - next_poll = match iface.poll_delay(loop_start, &self.sockets) { + next_poll = match iface.poll_delay(loop_start) { Some(smoltcp::time::Duration::ZERO) => None, Some(delay) => { trace!("TCP Virtual interface delayed next poll by {}", delay); @@ -203,14 +192,13 @@ impl VirtualInterfacePoll for TcpVirtualInterface { match event { Event::ClientConnectionInitiated(port_forward, virtual_port) => { let client_socket = TcpVirtualInterface::new_client_socket()?; - let client_handle = self.sockets.add(client_socket); + let client_handle = iface.add_socket(client_socket); // Add handle to map port_client_handle_map.insert(virtual_port, client_handle); send_queue.insert(virtual_port, VecDeque::new()); - let client_socket = self.sockets.get_mut::(client_handle); - let context = iface.context(); + let (client_socket, context) = iface.get_socket_and_context::(client_handle); client_socket .connect( @@ -221,13 +209,13 @@ impl VirtualInterfacePoll for TcpVirtualInterface { ), (IpAddress::from(self.source_peer_ip), virtual_port.num()), ) - .context("Virtual server socket failed to listen")?; + .with_context(|| "Virtual server socket failed to listen")?; next_poll = None; } Event::ClientConnectionDropped(virtual_port) => { if let Some(client_handle) = port_client_handle_map.get(&virtual_port) { - let client_socket = self.sockets.get_mut::(*client_handle); + let client_socket = iface.get_socket::(*client_handle); client_socket.close(); next_poll = None; } @@ -238,7 +226,7 @@ impl VirtualInterfacePoll for TcpVirtualInterface { next_poll = None; } } - Event::VirtualDeviceFed(PortProtocol::Tcp) => { + Event::VirtualDeviceFed(protocol) if protocol == PortProtocol::Tcp => { next_poll = None; } _ => {} @@ -248,10 +236,3 @@ impl VirtualInterfacePoll for TcpVirtualInterface { } } } - -const fn addr_length(addr: &IpAddress) -> u8 { - match addr.version() { - IpVersion::Ipv4 => 32, - IpVersion::Ipv6 => 128, - } -} diff --git a/src/virtual_iface/udp.rs b/src/virtual_iface/udp.rs index cb643c9..d939132 100644 --- a/src/virtual_iface/udp.rs +++ b/src/virtual_iface/udp.rs @@ -1,23 +1,18 @@ -use crate::config::PortForwardConfig; +use anyhow::Context; +use std::collections::{HashMap, HashSet, VecDeque}; +use std::net::IpAddr; + use crate::events::Event; +use crate::{Bus, PortProtocol}; +use async_trait::async_trait; +use smoltcp::iface::{InterfaceBuilder, SocketHandle}; +use smoltcp::socket::{UdpPacketMetadata, UdpSocket, UdpSocketBuffer}; +use smoltcp::wire::{IpAddress, IpCidr}; +use std::time::Duration; + +use crate::config::PortForwardConfig; use crate::virtual_device::VirtualIpDevice; use crate::virtual_iface::{VirtualInterfacePoll, VirtualPort}; -use crate::{Bus, PortProtocol}; -use anyhow::Context; -use async_trait::async_trait; -use bytes::Bytes; -use smoltcp::iface::PollResult; -use smoltcp::{ - iface::{Config, Interface, SocketHandle, SocketSet}, - socket::udp::{self, UdpMetadata}, - time::Instant, - wire::{HardwareAddress, IpAddress, IpCidr, IpVersion}, -}; -use std::{ - collections::{HashMap, HashSet, VecDeque}, - net::IpAddr, - time::Duration, -}; const MAX_PACKET: usize = 65536; @@ -25,7 +20,6 @@ pub struct UdpVirtualInterface { source_peer_ip: IpAddr, port_forwards: Vec, bus: Bus, - sockets: SocketSet<'static>, } impl UdpVirtualInterface { @@ -39,47 +33,44 @@ impl UdpVirtualInterface { .collect(), source_peer_ip, bus, - sockets: SocketSet::new([]), } } - fn new_server_socket(port_forward: PortForwardConfig) -> anyhow::Result> { - static mut UDP_SERVER_RX_META: [udp::PacketMetadata; 0] = []; + fn new_server_socket(port_forward: PortForwardConfig) -> anyhow::Result> { + static mut UDP_SERVER_RX_META: [UdpPacketMetadata; 0] = []; static mut UDP_SERVER_RX_DATA: [u8; 0] = []; - static mut UDP_SERVER_TX_META: [udp::PacketMetadata; 0] = []; + static mut UDP_SERVER_TX_META: [UdpPacketMetadata; 0] = []; static mut UDP_SERVER_TX_DATA: [u8; 0] = []; - let udp_rx_buffer = - udp::PacketBuffer::new(unsafe { &mut UDP_SERVER_RX_META[..] }, unsafe { - &mut UDP_SERVER_RX_DATA[..] - }); - let udp_tx_buffer = - udp::PacketBuffer::new(unsafe { &mut UDP_SERVER_TX_META[..] }, unsafe { - &mut UDP_SERVER_TX_DATA[..] - }); - let mut socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer); + let udp_rx_buffer = UdpSocketBuffer::new(unsafe { &mut UDP_SERVER_RX_META[..] }, unsafe { + &mut UDP_SERVER_RX_DATA[..] + }); + let udp_tx_buffer = UdpSocketBuffer::new(unsafe { &mut UDP_SERVER_TX_META[..] }, unsafe { + &mut UDP_SERVER_TX_DATA[..] + }); + let mut socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer); socket .bind(( IpAddress::from(port_forward.destination.ip()), port_forward.destination.port(), )) - .context("UDP virtual server socket failed to bind")?; + .with_context(|| "UDP virtual server socket failed to bind")?; Ok(socket) } fn new_client_socket( source_peer_ip: IpAddr, client_port: VirtualPort, - ) -> anyhow::Result> { - let rx_meta = vec![udp::PacketMetadata::EMPTY; 10]; - let tx_meta = vec![udp::PacketMetadata::EMPTY; 10]; + ) -> anyhow::Result> { + let rx_meta = vec![UdpPacketMetadata::EMPTY; 10]; + let tx_meta = vec![UdpPacketMetadata::EMPTY; 10]; let rx_data = vec![0u8; MAX_PACKET]; let tx_data = vec![0u8; MAX_PACKET]; - let udp_rx_buffer = udp::PacketBuffer::new(rx_meta, rx_data); - let udp_tx_buffer = udp::PacketBuffer::new(tx_meta, tx_data); - let mut socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer); + let udp_rx_buffer = UdpSocketBuffer::new(rx_meta, rx_data); + let udp_tx_buffer = UdpSocketBuffer::new(tx_meta, tx_data); + let mut socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer); socket .bind((IpAddress::from(source_peer_ip), client_port.num())) - .context("UDP virtual client failed to bind")?; + .with_context(|| "UDP virtual client failed to bind")?; Ok(socket) } @@ -91,32 +82,26 @@ impl UdpVirtualInterface { } addresses .into_iter() - .map(|addr| IpCidr::new(addr, addr_length(&addr))) + .map(|addr| IpCidr::new(addr, 32)) .collect() } } #[async_trait] impl VirtualInterfacePoll for UdpVirtualInterface { - async fn poll_loop(mut self, mut device: VirtualIpDevice) -> anyhow::Result<()> { + async fn poll_loop(self, device: VirtualIpDevice) -> anyhow::Result<()> { // Create CIDR block for source peer IP + each port forward IP let addresses = self.addresses(); - let config = Config::new(HardwareAddress::Ip); // Create virtual interface (contains smoltcp state machine) - let mut iface = Interface::new(config, &mut device, Instant::now()); - iface.update_ip_addrs(|ip_addrs| { - addresses.into_iter().for_each(|addr| { - ip_addrs - .push(addr) - .expect("maximum number of IPs in UDP interface reached"); - }); - }); + let mut iface = InterfaceBuilder::new(device, vec![]) + .ip_addrs(addresses) + .finalize(); // Create virtual server for each port forward for port_forward in self.port_forwards.iter() { let server_socket = UdpVirtualInterface::new_server_socket(*port_forward)?; - self.sockets.add(server_socket); + iface.add_socket(server_socket); } // The next time to poll the interface. Can be None for instant poll. @@ -129,7 +114,7 @@ impl VirtualInterfacePoll for UdpVirtualInterface { let mut port_client_handle_map: HashMap = HashMap::new(); // Data packets to send from a virtual client - let mut send_queue: HashMap> = + let mut send_queue: HashMap)>> = HashMap::new(); loop { @@ -141,12 +126,16 @@ impl VirtualInterfacePoll for UdpVirtualInterface { } => { let loop_start = smoltcp::time::Instant::now(); - if iface.poll(loop_start, &mut device, &mut self.sockets) == PollResult::SocketStateChanged { - log::trace!("UDP virtual interface polled some packets to be processed"); + match iface.poll(loop_start) { + Ok(processed) if processed => { + trace!("UDP virtual interface polled some packets to be processed"); + } + Err(e) => error!("UDP virtual interface poll error: {:?}", e), + _ => {} } for (virtual_port, client_handle) in port_client_handle_map.iter() { - let client_socket = self.sockets.get_mut::(*client_handle); + let client_socket = iface.get_socket::(*client_handle); if client_socket.can_send() { if let Some(send_queue) = send_queue.get_mut(virtual_port) { let to_transfer = send_queue.pop_front(); @@ -154,7 +143,7 @@ impl VirtualInterfacePoll for UdpVirtualInterface { client_socket .send_slice( &data, - UdpMetadata::from(port_forward.destination), + (IpAddress::from(port_forward.destination.ip()), port_forward.destination.port()).into(), ) .unwrap_or_else(|e| { error!( @@ -169,7 +158,7 @@ impl VirtualInterfacePoll for UdpVirtualInterface { match client_socket.recv() { Ok((data, _peer)) => { if !data.is_empty() { - endpoint.send(Event::RemoteData(*virtual_port, data.to_vec().into())); + endpoint.send(Event::RemoteData(*virtual_port, data.to_vec())); } } Err(e) => { @@ -182,7 +171,7 @@ impl VirtualInterfacePoll for UdpVirtualInterface { } // The virtual interface determines the next time to poll (this is to reduce unnecessary polls) - next_poll = match iface.poll_delay(loop_start, &self.sockets) { + next_poll = match iface.poll_delay(loop_start) { Some(smoltcp::time::Duration::ZERO) => None, Some(delay) => { trace!("UDP Virtual interface delayed next poll by {}", delay); @@ -200,7 +189,7 @@ impl VirtualInterfacePoll for UdpVirtualInterface { } else { // Client socket does not exist let client_socket = UdpVirtualInterface::new_client_socket(self.source_peer_ip, virtual_port)?; - let client_handle = self.sockets.add(client_socket); + let client_handle = iface.add_socket(client_socket); // Add handle to map port_client_handle_map.insert(virtual_port, client_handle); @@ -208,7 +197,7 @@ impl VirtualInterfacePoll for UdpVirtualInterface { } next_poll = None; } - Event::VirtualDeviceFed(PortProtocol::Udp) => { + Event::VirtualDeviceFed(protocol) if protocol == PortProtocol::Udp => { next_poll = None; } _ => {} @@ -218,10 +207,3 @@ impl VirtualInterfacePoll for UdpVirtualInterface { } } } - -const fn addr_length(addr: &IpAddress) -> u8 { - match addr.version() { - IpVersion::Ipv4 => 32, - IpVersion::Ipv6 => 128, - } -} diff --git a/src/wg.rs b/src/wg.rs index f114c43..18ef7d5 100644 --- a/src/wg.rs +++ b/src/wg.rs @@ -1,4 +1,4 @@ -use std::net::{IpAddr, SocketAddr}; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use std::time::Duration; use crate::Bus; @@ -9,7 +9,6 @@ use boringtun::noise::{Tunn, TunnResult}; use log::Level; use smoltcp::wire::{IpProtocol, IpVersion, Ipv4Packet, Ipv6Packet}; use tokio::net::UdpSocket; -use tokio::sync::Mutex; use crate::config::{Config, PortProtocol}; use crate::events::Event; @@ -24,7 +23,7 @@ const MAX_PACKET: usize = 65536; pub struct WireGuardTunnel { pub(crate) source_peer_ip: IpAddr, /// `boringtun` peer/tunnel implementation, used for crypto & WG protocol. - peer: Mutex>, + peer: Box, /// The UDP socket for the public WireGuard endpoint to connect to. udp: UdpSocket, /// The address of the public WireGuard endpoint (UDP). @@ -37,11 +36,11 @@ impl WireGuardTunnel { /// Initialize a new WireGuard tunnel. pub async fn new(config: &Config, bus: Bus) -> anyhow::Result { let source_peer_ip = config.source_peer_ip; - let peer = Mutex::new(Box::new(Self::create_tunnel(config)?)); + let peer = Self::create_tunnel(config)?; let endpoint = config.endpoint_addr; let udp = UdpSocket::bind(config.endpoint_bind_addr) .await - .context("Failed to create UDP socket for WireGuard connection")?; + .with_context(|| "Failed to create UDP socket for WireGuard connection")?; Ok(Self { source_peer_ip, @@ -56,16 +55,12 @@ impl WireGuardTunnel { pub async fn send_ip_packet(&self, packet: &[u8]) -> anyhow::Result<()> { trace_ip_packet("Sending IP packet", packet); let mut send_buf = [0u8; MAX_PACKET]; - let encapsulate_result = { - let mut peer = self.peer.lock().await; - peer.encapsulate(packet, &mut send_buf) - }; - match encapsulate_result { + match self.peer.encapsulate(packet, &mut send_buf) { TunnResult::WriteToNetwork(packet) => { self.udp .send_to(packet, self.endpoint) .await - .context("Failed to send encrypted IP packet to WireGuard endpoint.")?; + .with_context(|| "Failed to send encrypted IP packet to WireGuard endpoint.")?; debug!( "Sent {} bytes to WireGuard endpoint (encrypted IP packet)", packet.len() @@ -109,7 +104,7 @@ impl WireGuardTunnel { loop { let mut send_buf = [0u8; MAX_PACKET]; - let tun_result = { self.peer.lock().await.update_timers(&mut send_buf) }; + let tun_result = self.peer.update_timers(&mut send_buf); self.handle_routine_tun_result(tun_result).await; } } @@ -136,11 +131,7 @@ impl WireGuardTunnel { warn!("Wireguard handshake has expired!"); let mut buf = vec![0u8; MAX_PACKET]; - let result = self - .peer - .lock() - .await - .format_handshake_initiation(&mut buf[..], false); + let result = self.peer.format_handshake_initiation(&mut buf[..], false); self.handle_routine_tun_result(result).await } @@ -181,11 +172,7 @@ impl WireGuardTunnel { }; let data = &recv_buf[..size]; - let decapsulate_result = { - let mut peer = self.peer.lock().await; - peer.decapsulate(None, data, &mut send_buf) - }; - match decapsulate_result { + match self.peer.decapsulate(None, data, &mut send_buf) { TunnResult::WriteToNetwork(packet) => { match self.udp.send_to(packet, self.endpoint).await { Ok(_) => {} @@ -194,10 +181,9 @@ impl WireGuardTunnel { continue; } }; - let mut peer = self.peer.lock().await; loop { let mut send_buf = [0u8; MAX_PACKET]; - match peer.decapsulate(None, &[], &mut send_buf) { + match self.peer.decapsulate(None, &[], &mut send_buf) { TunnResult::WriteToNetwork(packet) => { match self.udp.send_to(packet, self.endpoint).await { Ok(_) => {} @@ -223,7 +209,7 @@ impl WireGuardTunnel { trace_ip_packet("Received IP packet", packet); if let Some(proto) = self.route_protocol(packet) { - endpoint.send(Event::InboundInternetPacket(proto, packet.to_vec().into())); + endpoint.send(Event::InboundInternetPacket(proto, packet.into())); } } _ => {} @@ -231,20 +217,17 @@ impl WireGuardTunnel { } } - fn create_tunnel(config: &Config) -> anyhow::Result { - let private = config.private_key.as_ref().clone(); - let public = *config.endpoint_public_key.as_ref(); - + fn create_tunnel(config: &Config) -> anyhow::Result> { Tunn::new( - private, - public, - config.preshared_key, + config.private_key.clone(), + config.endpoint_public_key.clone(), + None, config.keepalive_seconds, 0, None, ) .map_err(|s| anyhow::anyhow!("{}", s)) - .context("Failed to initialize boringtun Tunn") + .with_context(|| "Failed to initialize boringtun Tunn") } /// Determine the inner protocol of the incoming IP packet (TCP/UDP). @@ -253,8 +236,8 @@ impl WireGuardTunnel { Ok(IpVersion::Ipv4) => Ipv4Packet::new_checked(&packet) .ok() // Only care if the packet is destined for this tunnel - .filter(|packet| packet.dst_addr() == self.source_peer_ip) - .and_then(|packet| match packet.next_header() { + .filter(|packet| Ipv4Addr::from(packet.dst_addr()) == self.source_peer_ip) + .and_then(|packet| match packet.protocol() { IpProtocol::Tcp => Some(PortProtocol::Tcp), IpProtocol::Udp => Some(PortProtocol::Udp), // Unrecognized protocol, so we cannot determine where to route @@ -263,7 +246,7 @@ impl WireGuardTunnel { Ok(IpVersion::Ipv6) => Ipv6Packet::new_checked(&packet) .ok() // Only care if the packet is destined for this tunnel - .filter(|packet| packet.dst_addr() == self.source_peer_ip) + .filter(|packet| Ipv6Addr::from(packet.dst_addr()) == self.source_peer_ip) .and_then(|packet| match packet.next_header() { IpProtocol::Tcp => Some(PortProtocol::Tcp), IpProtocol::Udp => Some(PortProtocol::Udp),