mirror of
https://github.com/dndx/phantun.git
synced 2025-09-17 04:34:29 +08:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9ff691d063 | ||
|
b5e79653f0 | ||
|
f496a7919b | ||
|
bf6b9bc2ff | ||
|
47b9037968 | ||
|
c2341b6662 | ||
|
a3eff42453 | ||
|
87a42a1e23 | ||
|
851750b13d | ||
|
b89b683bb2 | ||
|
838cfa6738 |
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -26,9 +26,9 @@ jobs:
|
|||||||
- aarch64-unknown-linux-gnu
|
- aarch64-unknown-linux-gnu
|
||||||
- aarch64-unknown-linux-musl
|
- aarch64-unknown-linux-musl
|
||||||
- mips-unknown-linux-gnu
|
- mips-unknown-linux-gnu
|
||||||
- mips-unknown-linux-musl
|
#- mips-unknown-linux-musl # currently does not build due to libc::sock_txtime not found, need a newer release of libc
|
||||||
- mipsel-unknown-linux-gnu
|
- mipsel-unknown-linux-gnu
|
||||||
- mipsel-unknown-linux-musl
|
#- mipsel-unknown-linux-musl
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
72
README.md
72
README.md
@@ -35,7 +35,7 @@ Table of Contents
|
|||||||
|
|
||||||
# Latest release
|
# Latest release
|
||||||
|
|
||||||
[v0.3.2](https://github.com/dndx/phantun/releases/tag/v0.3.2)
|
[v0.4.2](https://github.com/dndx/phantun/releases/tag/v0.4.2)
|
||||||
|
|
||||||
# Overview
|
# Overview
|
||||||
|
|
||||||
@@ -72,30 +72,32 @@ It is also assumed that **Phantun Client** listens for incoming UDP packets at
|
|||||||
`127.0.0.1:1234` (the `--local` option for client) and connects to Phantun Server at `10.0.0.1:4567`
|
`127.0.0.1:1234` (the `--local` option for client) and connects to Phantun Server at `10.0.0.1:4567`
|
||||||
(the `--remote` option for client).
|
(the `--remote` option for client).
|
||||||
|
|
||||||
Phantun creates TUN interface for both the Client and Server. For Client, Phantun assigns itself the IP address
|
Phantun creates TUN interface for both the Client and Server. For **Client**, Phantun assigns itself the IP address
|
||||||
`192.168.200.2` by default and for Server, it assigns `192.168.201.2` by default. Therefore, your Kernel must have
|
`192.168.200.2` and `fcc8::2` by default.
|
||||||
`net.ipv4.ip_forward` enabled and setup appropriate iptables rules for NAT between your physical
|
For **Server**, it assigns `192.168.201.2` and `fcc9::2` by default. Therefore, your Kernel must have
|
||||||
NIC address and Phantun's TUN interface address.
|
IPv4/IPv6 forwarding enabled and setup appropriate iptables/nftables rules for NAT between your physical
|
||||||
|
NIC address and Phantun's Tun interface address.
|
||||||
|
|
||||||
You may customize the name of Tun interface created by Phantun and the assigned addresses. Please
|
You may customize the name of Tun interface created by Phantun and the assigned addresses. Please
|
||||||
run the executable with `-h` options to see how to change them.
|
run the executable with `-h` options to see how to change them.
|
||||||
|
|
||||||
Another way to help understand this network topology (please see the diagram above for an illustration of this topology):
|
Another way to help understand this network topology (please see the diagram above for an illustration of this topology):
|
||||||
|
|
||||||
Phantun Client is like a machine with private IP address (`192.168.200.2`) behind a router.
|
Phantun Client is like a machine with private IP address (`192.168.200.2`/`fcc8::2`) behind a router.
|
||||||
In order for it to reach the Internet, you will need to SNAT the private IP address before it's traffic
|
In order for it to reach the Internet, you will need to SNAT the private IP address before it's traffic
|
||||||
leaves the NIC.
|
leaves the NIC.
|
||||||
|
|
||||||
Phantun Server is like a server with private IP address (`192.168.201.2`) behind a router.
|
Phantun Server is like a server with private IP address (`192.168.201.2`/`fcc9::2`) behind a router.
|
||||||
In order to access it from the Internet, you need to `DNAT` it's listening port on the router
|
In order to access it from the Internet, you need to `DNAT` it's listening port on the router
|
||||||
and change the destination IP address to where the server is listening for incoming connections.
|
and change the destination IP address to where the server is listening for incoming connections.
|
||||||
|
|
||||||
In those cases, the machine/iptables running Phantun acts as the "router" that allows Phantun
|
In those cases, the machine/iptables running Phantun acts as the "router" that allows Phantun
|
||||||
to communicate with outside using it's private IP addresses.
|
to communicate with outside using it's private IP addresses.
|
||||||
|
|
||||||
As of Phantun v0.2.2, IPv6 support for UDP endpoints has been added, however Fake TCP IPv6 support
|
As of Phantun v0.4.1, IPv6 is fully supported for both TCP and UDP sides.
|
||||||
has not been finished yet. To specify an IPv6 address, use the following format: `[::1]:1234` with
|
To specify an IPv6 address, use the following format: `[::1]:1234` with
|
||||||
the command line options.
|
the command line options. Resolving AAAA record is also supported. Please run the program
|
||||||
|
with `-h` to see detailed options on how to control the IPv6 behavior.
|
||||||
|
|
||||||
[Back to TOC](#table-of-contents)
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
@@ -103,6 +105,12 @@ the command line options.
|
|||||||
|
|
||||||
Edit `/etc/sysctl.conf`, add `net.ipv4.ip_forward=1` and run `sudo sysctl -p /etc/sysctl.conf`.
|
Edit `/etc/sysctl.conf`, add `net.ipv4.ip_forward=1` and run `sudo sysctl -p /etc/sysctl.conf`.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>IPv6 specific config</summary>
|
||||||
|
|
||||||
|
`net.ipv6.conf.all.forwarding=1` will need to be set as well.
|
||||||
|
</details>
|
||||||
|
|
||||||
[Back to TOC](#table-of-contents)
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
## 2. Add required firewall rules
|
## 2. Add required firewall rules
|
||||||
@@ -128,12 +136,16 @@ table inet nat {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: The above rule uses `inet` as the table family type, so it is compatible with
|
||||||
|
both IPv4 and IPv6 usage.
|
||||||
|
|
||||||
[Back to TOC](#table-of-contents)
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
#### Using iptables
|
#### Using iptables
|
||||||
|
|
||||||
```
|
```
|
||||||
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||||
|
ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||||
```
|
```
|
||||||
|
|
||||||
[Back to TOC](#table-of-contents)
|
[Back to TOC](#table-of-contents)
|
||||||
@@ -150,10 +162,11 @@ actual TCP port number used by Phantun server
|
|||||||
#### Using nftables
|
#### Using nftables
|
||||||
|
|
||||||
```
|
```
|
||||||
table ip nat {
|
table inet nat {
|
||||||
chain prerouting {
|
chain prerouting {
|
||||||
type nat hook prerouting priority dstnat; policy accept;
|
type nat hook prerouting priority dstnat; policy accept;
|
||||||
iif eth0 tcp dport 4567 dnat to 192.168.201.2
|
iif eth0 tcp dport 4567 dnat ip to 192.168.201.2
|
||||||
|
iif eth0 tcp dport 4567 dnat ip6 to fcc9::2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -164,6 +177,7 @@ table ip nat {
|
|||||||
|
|
||||||
```
|
```
|
||||||
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 4567 -j DNAT --to-destination 192.168.201.2
|
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 4567 -j DNAT --to-destination 192.168.201.2
|
||||||
|
ip6tables -t nat -A PREROUTING -p tcp -i eth0 --dport 4567 -j DNAT --to-destination fcc9::2
|
||||||
```
|
```
|
||||||
|
|
||||||
[Back to TOC](#table-of-contents)
|
[Back to TOC](#table-of-contents)
|
||||||
@@ -202,6 +216,10 @@ Or use host name with `--remote`:
|
|||||||
RUST_LOG=info /usr/local/bin/phantun_server --local 4567 --remote example.com:1234
|
RUST_LOG=info /usr/local/bin/phantun_server --local 4567 --remote example.com:1234
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: Server by default assigns both IPv4 and IPv6 private address to the Tun interface.
|
||||||
|
If you do not wish to use IPv6, you can simply skip creating the IPv6 DNAT rule above and
|
||||||
|
the presence of IPv6 address on the Tun interface should have no side effect to the server.
|
||||||
|
|
||||||
[Back to TOC](#table-of-contents)
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
### Client
|
### Client
|
||||||
@@ -219,12 +237,22 @@ Or use host name with `--remote`:
|
|||||||
RUST_LOG=info /usr/local/bin/phantun_client --local 127.0.0.1:1234 --remote example.com:4567
|
RUST_LOG=info /usr/local/bin/phantun_client --local 127.0.0.1:1234 --remote example.com:4567
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>IPv6 specific config</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
RUST_LOG=info /usr/local/bin/phantun_client --local 127.0.0.1:1234 --remote [fdxx::1234]:4567
|
||||||
|
```
|
||||||
|
|
||||||
|
Domain name with AAAA record is also supported.
|
||||||
|
</details>
|
||||||
|
|
||||||
[Back to TOC](#table-of-contents)
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
# MTU overhead
|
# MTU overhead
|
||||||
|
|
||||||
Phantun aims to keep tunneling overhead to the minimum. The overhead compared to a plain UDP packet
|
Phantun aims to keep tunneling overhead to the minimum. The overhead compared to a plain UDP packet
|
||||||
is the following:
|
is the following (using IPv4 below as an example):
|
||||||
|
|
||||||
**Standard UDP packet:** `20 byte IP header + 8 byte UDP header = 28 bytes`
|
**Standard UDP packet:** `20 byte IP header + 8 byte UDP header = 28 bytes`
|
||||||
|
|
||||||
@@ -248,18 +276,23 @@ For people who use Phantun to tunnel [WireGuard®](https://www.wireguard.com) UD
|
|||||||
out the correct MTU to use for your WireGuard interface.
|
out the correct MTU to use for your WireGuard interface.
|
||||||
|
|
||||||
```
|
```
|
||||||
WireGuard MTU = Interface MTU - IP header (20 bytes) - TCP header (20 bytes) - WireGuard overhead (32 bytes)
|
WireGuard MTU = Interface MTU - IPv4 header (20 bytes) - TCP header (20 bytes) - WireGuard overhead (32 bytes)
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
WireGuard MTU = Interface MTU - IPv6 header (40 bytes) - TCP header (20 bytes) - WireGuard overhead (32 bytes)
|
||||||
```
|
```
|
||||||
|
|
||||||
For example, for a Ethernet interface with 1500 bytes MTU, the WireGuard interface MTU should be set as:
|
For example, for a Ethernet interface with 1500 bytes MTU, the WireGuard interface MTU should be set as:
|
||||||
|
|
||||||
```
|
IPv4: `1500 - 20 - 20 - 32 = 1428 bytes`
|
||||||
1500 - 20 - 20 - 32 = 1428 bytes
|
IPv6: `1500 - 40 - 20 - 32 = 1408 bytes`
|
||||||
```
|
|
||||||
|
|
||||||
The resulted Phantun TCP data packet will be 1500 bytes which does not exceed the
|
The resulted Phantun TCP data packet will be 1500 bytes which does not exceed the
|
||||||
interface MTU of 1500. Please note it is strongly recommended to use the same interface
|
interface MTU of 1500. Please note it is strongly recommended to use the same interface
|
||||||
MTU for both ends of a WireGuard tunnel, or unexected packet loss may occur and these issues are
|
MTU for both ends of a WireGuard tunnel, or unexpected packet loss may occur and these issues are
|
||||||
generally very hard to troubleshoot.
|
generally very hard to troubleshoot.
|
||||||
|
|
||||||
[Back to TOC](#table-of-contents)
|
[Back to TOC](#table-of-contents)
|
||||||
@@ -300,7 +333,6 @@ Test command: `iperf3 -c <IP> -p <PORT> -R -u -l 1400 -b 1000m -t 30 -P 5`
|
|||||||
|
|
||||||
# Future plans
|
# Future plans
|
||||||
|
|
||||||
* IPv6 support for fake-tcp
|
|
||||||
* Load balancing a single UDP stream into multiple TCP streams
|
* Load balancing a single UDP stream into multiple TCP streams
|
||||||
* Integration tests
|
* Integration tests
|
||||||
* Auto insertion/removal of required firewall rules
|
* Auto insertion/removal of required firewall rules
|
||||||
@@ -328,7 +360,7 @@ Here is a quick overview of comparison between those two to help you choose:
|
|||||||
| Tunneling MTU overhead | 12 bytes | 44 bytes |
|
| Tunneling MTU overhead | 12 bytes | 44 bytes |
|
||||||
| Seprate TCP connections for each UDP connection | Client/Server | Server only |
|
| Seprate TCP connections for each UDP connection | Client/Server | Server only |
|
||||||
| Anti-replay, encryption | ❌ | ✅ |
|
| Anti-replay, encryption | ❌ | ✅ |
|
||||||
| IPv6 | UDP only | ✅ |
|
| IPv6 | ✅ | ✅ |
|
||||||
|
|
||||||
[Back to TOC](#table-of-contents)
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@ benchmark = []
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
pnet = "0.29"
|
pnet = "0.30"
|
||||||
tokio = { version = "1.14", features = ["full"] }
|
tokio = { version = "1.14", features = ["full"] }
|
||||||
rand = { version = "0.8", features = ["small_rng"] }
|
rand = { version = "0.8", features = ["small_rng"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "phantun"
|
name = "phantun"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Datong Sun <dndx@idndx.com>"]
|
authors = ["Datong Sun <dndx@idndx.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
@@ -21,4 +21,4 @@ pretty_env_logger = "0.4"
|
|||||||
tokio-tun = "0.5"
|
tokio-tun = "0.5"
|
||||||
num_cpus = "1.13"
|
num_cpus = "1.13"
|
||||||
neli = "0.6"
|
neli = "0.6"
|
||||||
nix = "0.23"
|
nix = "0.24"
|
||||||
|
@@ -4,6 +4,7 @@ use fake_tcp::{Socket, Stack};
|
|||||||
use log::{debug, error, info};
|
use log::{debug, error, info};
|
||||||
use phantun::utils::{assign_ipv6_address, new_udp_reuseport};
|
use phantun::utils::{assign_ipv6_address, new_udp_reuseport};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::{Ipv4Addr, SocketAddr};
|
use std::net::{Ipv4Addr, SocketAddr};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -73,7 +74,7 @@ async fn main() -> io::Result<()> {
|
|||||||
.long("ipv4-only")
|
.long("ipv4-only")
|
||||||
.short('4')
|
.short('4')
|
||||||
.required(false)
|
.required(false)
|
||||||
.help("Do not assign IPv6 addresses to Tun interface")
|
.help("Only use IPv4 address when connecting to remote")
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.conflicts_with_all(&["tun_local6", "tun_peer6"]),
|
.conflicts_with_all(&["tun_local6", "tun_peer6"]),
|
||||||
)
|
)
|
||||||
@@ -83,7 +84,7 @@ async fn main() -> io::Result<()> {
|
|||||||
.required(false)
|
.required(false)
|
||||||
.value_name("IP")
|
.value_name("IP")
|
||||||
.help("Sets the Tun interface IPv6 local address (O/S's end)")
|
.help("Sets the Tun interface IPv6 local address (O/S's end)")
|
||||||
.default_value("fec8::1")
|
.default_value("fcc8::1")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@@ -94,7 +95,18 @@ async fn main() -> io::Result<()> {
|
|||||||
.help("Sets the Tun interface IPv6 destination (peer) address (Phantun Client's end). \
|
.help("Sets the Tun interface IPv6 destination (peer) address (Phantun Client's end). \
|
||||||
You will need to setup SNAT/MASQUERADE rules on your Internet facing interface \
|
You will need to setup SNAT/MASQUERADE rules on your Internet facing interface \
|
||||||
in order for Phantun Client to connect to Phantun Server")
|
in order for Phantun Client to connect to Phantun Server")
|
||||||
.default_value("fec8::2")
|
.default_value("fcc8::2")
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("handshake_packet")
|
||||||
|
.long("handshake-packet")
|
||||||
|
.required(false)
|
||||||
|
.value_name("PATH")
|
||||||
|
.help("Specify a file, which, after TCP handshake, its content will be sent as the \
|
||||||
|
first data packet to the server.\n\
|
||||||
|
Note: ensure this file's size does not exceed the MTU of the outgoing interface. \
|
||||||
|
The content is always sent out in a single packet and will not be further segmented")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
@@ -139,6 +151,10 @@ async fn main() -> io::Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let tun_name = matches.value_of("tun").unwrap();
|
let tun_name = matches.value_of("tun").unwrap();
|
||||||
|
let handshake_packet: Option<Vec<u8>> = matches
|
||||||
|
.value_of("handshake_packet")
|
||||||
|
.map(fs::read)
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
let num_cpus = num_cpus::get();
|
let num_cpus = num_cpus::get();
|
||||||
info!("{} cores available", num_cpus);
|
info!("{} cores available", num_cpus);
|
||||||
@@ -186,9 +202,17 @@ async fn main() -> io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let sock = Arc::new(sock.unwrap());
|
let sock = Arc::new(sock.unwrap());
|
||||||
|
if let Some(ref p) = handshake_packet {
|
||||||
|
if sock.send(p).await.is_none() {
|
||||||
|
error!("Failed to send handshake packet to remote, closing connection.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("Sent handshake packet to: {}", sock);
|
||||||
|
}
|
||||||
|
|
||||||
// send first packet
|
// send first packet
|
||||||
let res = sock.send(&buf_r[..size]).await;
|
if sock.send(&buf_r[..size]).await.is_none() {
|
||||||
if res.is_none() {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@ use fake_tcp::packet::MAX_PACKET_LEN;
|
|||||||
use fake_tcp::Stack;
|
use fake_tcp::Stack;
|
||||||
use log::{debug, error, info};
|
use log::{debug, error, info};
|
||||||
use phantun::utils::{assign_ipv6_address, new_udp_reuseport};
|
use phantun::utils::{assign_ipv6_address, new_udp_reuseport};
|
||||||
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -83,7 +84,7 @@ async fn main() -> io::Result<()> {
|
|||||||
.required(false)
|
.required(false)
|
||||||
.value_name("IP")
|
.value_name("IP")
|
||||||
.help("Sets the Tun interface IPv6 local address (O/S's end)")
|
.help("Sets the Tun interface IPv6 local address (O/S's end)")
|
||||||
.default_value("fec9::1")
|
.default_value("fcc9::1")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@@ -94,7 +95,18 @@ async fn main() -> io::Result<()> {
|
|||||||
.help("Sets the Tun interface IPv6 destination (peer) address (Phantun Client's end). \
|
.help("Sets the Tun interface IPv6 destination (peer) address (Phantun Client's end). \
|
||||||
You will need to setup SNAT/MASQUERADE rules on your Internet facing interface \
|
You will need to setup SNAT/MASQUERADE rules on your Internet facing interface \
|
||||||
in order for Phantun Client to connect to Phantun Server")
|
in order for Phantun Client to connect to Phantun Server")
|
||||||
.default_value("fec9::2")
|
.default_value("fcc9::2")
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("handshake_packet")
|
||||||
|
.long("handshake-packet")
|
||||||
|
.required(false)
|
||||||
|
.value_name("PATH")
|
||||||
|
.help("Specify a file, which, after TCP handshake, its content will be sent as the \
|
||||||
|
first data packet to the client.\n\
|
||||||
|
Note: ensure this file's size does not exceed the MTU of the outgoing interface. \
|
||||||
|
The content is always sent out in a single packet and will not be further segmented")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
@@ -137,6 +149,10 @@ async fn main() -> io::Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let tun_name = matches.value_of("tun").unwrap();
|
let tun_name = matches.value_of("tun").unwrap();
|
||||||
|
let handshake_packet: Option<Vec<u8>> = matches
|
||||||
|
.value_of("handshake_packet")
|
||||||
|
.map(fs::read)
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
let num_cpus = num_cpus::get();
|
let num_cpus = num_cpus::get();
|
||||||
info!("{} cores available", num_cpus);
|
info!("{} cores available", num_cpus);
|
||||||
@@ -169,6 +185,14 @@ async fn main() -> io::Result<()> {
|
|||||||
loop {
|
loop {
|
||||||
let sock = Arc::new(stack.accept().await);
|
let sock = Arc::new(stack.accept().await);
|
||||||
info!("New connection: {}", sock);
|
info!("New connection: {}", sock);
|
||||||
|
if let Some(ref p) = handshake_packet {
|
||||||
|
if sock.send(p).await.is_none() {
|
||||||
|
error!("Failed to send handshake packet to remote, closing connection.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("Sent handshake packet to: {}", sock);
|
||||||
|
}
|
||||||
|
|
||||||
let packet_received = Arc::new(Notify::new());
|
let packet_received = Arc::new(Notify::new());
|
||||||
let quit = CancellationToken::new();
|
let quit = CancellationToken::new();
|
||||||
|
Reference in New Issue
Block a user