Merge proxy/proxyd into single binary, make command line parsing more robust
This commit is contained in:
parent
152bb991d4
commit
5e394bca1e
13
README.md
13
README.md
@ -2,15 +2,16 @@
|
||||
|
||||
Proxy wireguard UDP packets over TCP/TLS
|
||||
|
||||
`wireguard-proxyd` is a server-side daemon to accept TCP connections from multiple clients and pipe data to and from the specified UDP port
|
||||
`wireguard-proxy` is a client-side daemon that accepts UDP packets on a local port from a single client, connects to a single remote TCP port, and pipes data between them
|
||||
`wireguard-proxy` has 2 modes:
|
||||
- server-side daemon to accept TCP connections from multiple clients and pipe data to and from the specified UDP port
|
||||
- client-side daemon that accepts UDP packets on a local port from a single client, connects to a single remote TCP port, and pipes data between them
|
||||
|
||||
Testing:
|
||||
|
||||
`udp-test` is a utility to send a UDP packet and then receive a UDP packet and ensure they are the same, this verifies packets sent through proxy/proxyd are unmolested
|
||||
`udp-test -s` runs udp-test against itself through proxyd/proxy by spawning actual binaries
|
||||
`udp-test -is` runs udp-test against itself through proxyd/proxy in same executable by using library, so does not test command line parsing etc
|
||||
`test.sh` runs udp-test against itself, then the udp-test self tests above, and then through proxyd/proxy in the shell script
|
||||
- `udp-test` is a utility to send a UDP packet and then receive a UDP packet and ensure they are the same, this verifies packets sent through proxy server/client are unmolested
|
||||
- `udp-test -s` runs udp-test against itself through proxy server/client by spawning actual binaries
|
||||
- `udp-test -is` runs udp-test against itself through proxy server/client in same executable by using library, so does not test command line parsing etc
|
||||
- `test.sh` runs udp-test against itself, the udp-test self tests above, and through proxy server/client in the shell script
|
||||
|
||||
Testing with GNU netcat:
|
||||
|
||||
|
@ -53,7 +53,6 @@ test_script:
|
||||
before_deploy:
|
||||
# TODO Update this to build the artifacts that matter to you
|
||||
- cargo rustc --target %TARGET% --release --bin wireguard-proxy -- -C lto
|
||||
- cargo rustc --target %TARGET% --release --bin wireguard-proxyd -- -C lto
|
||||
- ps: ci\before_deploy.ps1
|
||||
|
||||
deploy:
|
||||
|
@ -11,7 +11,6 @@ Set-Location $STAGE
|
||||
$ZIP = "$SRC_DIR\$($Env:CRATE_NAME)-$($Env:APPVEYOR_REPO_TAG_NAME)-$($Env:TARGET).zip"
|
||||
|
||||
# TODO Update this to package the right artifacts
|
||||
Copy-Item "$SRC_DIR\target\$($Env:TARGET)\release\wireguard-proxyd.exe" '.\'
|
||||
Copy-Item "$SRC_DIR\target\$($Env:TARGET)\release\wireguard-proxy.exe" '.\'
|
||||
|
||||
7z a "$ZIP" *
|
||||
|
@ -19,17 +19,16 @@ main() {
|
||||
|
||||
# TODO Update this to build the artifacts that matter to you
|
||||
cross rustc --bin wireguard-proxy --target $TARGET --release -- -C lto
|
||||
cross rustc --bin wireguard-proxyd --target $TARGET --release -- -C lto
|
||||
|
||||
# TODO Update this to package the right artifacts, this needs to handle .exe too...
|
||||
case $TARGET in
|
||||
x86_64-pc-windows-gnu)
|
||||
strip target/$TARGET/release/wireguard-proxy.exe target/$TARGET/release/wireguard-proxyd.exe || echo 'strip failed, ignoring...'
|
||||
cp target/$TARGET/release/wireguard-proxy.exe target/$TARGET/release/wireguard-proxyd.exe $stage/
|
||||
strip target/$TARGET/release/wireguard-proxy.exe || echo 'strip failed, ignoring...'
|
||||
cp target/$TARGET/release/wireguard-proxy.exe $stage/
|
||||
;;
|
||||
*)
|
||||
strip target/$TARGET/release/wireguard-proxy target/$TARGET/release/wireguard-proxyd || echo 'strip failed, ignoring...'
|
||||
cp target/$TARGET/release/wireguard-proxy target/$TARGET/release/wireguard-proxyd $stage/
|
||||
strip target/$TARGET/release/wireguard-proxy || echo 'strip failed, ignoring...'
|
||||
cp target/$TARGET/release/wireguard-proxy $stage/
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -70,41 +70,53 @@ impl Server {
|
||||
fn main() {
|
||||
let raw_args = env::args().collect();
|
||||
let args = Args::new(&raw_args);
|
||||
let mut first_arg = args.get_str(1, "127.0.0.1:51820");
|
||||
if first_arg.contains("-h") {
|
||||
println!(
|
||||
"usage: {} [-h] [-s run a self test through proxy/proxyd] [-is run a self test through proxy/proxyd without spawning other processes] [udp_host, 127.0.0.1:51820] [udp_target, 127.0.0.1:51820] [socket_timeout, 10]",
|
||||
args.get_str(0, "udp-test")
|
||||
);
|
||||
let default_udp_host_target = "127.0.0.1:51820";
|
||||
let default_socket_timeout = 10;
|
||||
let mut first_arg = args.get_str(&["-uh", "--udp-host"], default_udp_host_target);
|
||||
if args.flag("-h") || args.flag("--help"){
|
||||
println!(r#"usage: udp-test [options...]
|
||||
-h, --help print this usage text
|
||||
-s, --self-test run a self test through proxy
|
||||
-is, --internal-self-test run a self test through proxy without
|
||||
spawning other processes
|
||||
-uh, --udp-host <ip:port> UDP host to listen on, default: {}
|
||||
-ut, --udp-target <ip:port> UDP target to send packets to, default: {}
|
||||
-st, --socket-timeout <seconds> Socket timeout (time to wait for data)
|
||||
before terminating, default: {}
|
||||
"#, default_udp_host_target, default_udp_host_target, default_socket_timeout);
|
||||
return;
|
||||
} else if first_arg.contains("-s") {
|
||||
} else if args.flag("-s") || args.flag("--self-test") {
|
||||
// here is the hard work, we need to spawn proxyd and proxy from the same dir as udp-test...
|
||||
let host = "127.0.0.1:51822";
|
||||
let tcp_host = "127.0.0.1:5555";
|
||||
let sleep = Duration::from_secs(5);
|
||||
|
||||
let udp_test = args.get_str(0, "udp-test");
|
||||
let proxyd = udp_test.clone().replace("udp-test", "wireguard-proxyd");
|
||||
let udp_test = args.get_str_idx(0, "udp-test");
|
||||
let proxy = udp_test.clone().replace("udp-test", "wireguard-proxy");
|
||||
|
||||
println!("executing: {} '{}' '{}'", proxyd, tcp_host, host);
|
||||
let mut proxyd = Command::new(proxyd)
|
||||
println!("executing: {} -th '{}' -ut '{}'", proxy, tcp_host, host);
|
||||
let mut proxyd = Command::new(proxy.clone())
|
||||
.arg("-th")
|
||||
.arg(tcp_host)
|
||||
.arg("-ut")
|
||||
.arg(host)
|
||||
.spawn()
|
||||
.expect("wireguard-proxyd failed to launch");
|
||||
println!("waiting: {:?} for wireguard-proxyd to come up.....", sleep);
|
||||
.expect("wireguard-proxy server failed to launch");
|
||||
println!("waiting: {:?} for wireguard-proxy server to come up.....", sleep);
|
||||
thread::sleep(sleep);
|
||||
|
||||
println!("executing: {}", proxy);
|
||||
println!("executing: {} -tt {}", proxy, tcp_host);
|
||||
let mut proxy = Command::new(proxy)
|
||||
.arg("-tt")
|
||||
.arg(tcp_host)
|
||||
.spawn()
|
||||
.expect("wireguard-proxy failed to launch");
|
||||
println!("waiting: {:?} for wireguard-proxy to come up.....", sleep);
|
||||
.expect("wireguard-proxy client failed to launch");
|
||||
println!("waiting: {:?} for wireguard-proxy client to come up.....", sleep);
|
||||
thread::sleep(sleep);
|
||||
|
||||
println!("executing: {} '{}'", udp_test, host);
|
||||
println!("executing: {} -uh '{}'", udp_test, host);
|
||||
let mut udp_test = Command::new(udp_test)
|
||||
.arg("-uh")
|
||||
.arg(host)
|
||||
.spawn()
|
||||
.expect("udp-test failed to launch");
|
||||
@ -123,7 +135,7 @@ fn main() {
|
||||
.code()
|
||||
.expect("could not get udp-test exit code"),
|
||||
);
|
||||
} else if first_arg.contains("-is") {
|
||||
} else if args.flag("-is") || args.flag("--internal-self-test") {
|
||||
let host = "127.0.0.1:51822";
|
||||
let tcp_host = "127.0.0.1:5555";
|
||||
let sleep = Duration::from_secs(5);
|
||||
@ -142,9 +154,9 @@ fn main() {
|
||||
proxy_server.client_handler.udp_target, proxy_server.client_handler.socket_timeout,
|
||||
);
|
||||
|
||||
println!("executing: wireguard-proxyd '{}' '{}'", tcp_host, host);
|
||||
println!("executing: wireguard-proxy -th '{}' -ut '{}'", tcp_host, host);
|
||||
thread::spawn(move || proxy_server.start().expect("error running proxy_server"));
|
||||
println!("waiting: {:?} for wireguard-proxyd to come up.....", sleep);
|
||||
println!("waiting: {:?} for wireguard-proxy server to come up.....", sleep);
|
||||
thread::sleep(sleep);
|
||||
|
||||
let proxy_client = ProxyClient::new(
|
||||
@ -160,9 +172,9 @@ fn main() {
|
||||
proxy_client.socket_timeout,
|
||||
);
|
||||
|
||||
println!("executing: wireguard-proxy");
|
||||
println!("executing: wireguard-proxy -tt {}", tcp_host);
|
||||
thread::spawn(move || proxy_client.start().expect("error running proxy_client"));
|
||||
println!("waiting: {:?} for wireguard-proxy to come up.....", sleep);
|
||||
println!("waiting: {:?} for wireguard-proxy client to come up.....", sleep);
|
||||
thread::sleep(sleep);
|
||||
|
||||
first_arg = host;
|
||||
@ -170,8 +182,8 @@ fn main() {
|
||||
|
||||
let server = Server::new(
|
||||
first_arg.to_owned(),
|
||||
args.get_str(2, "127.0.0.1:51820").to_owned(),
|
||||
args.get(3, 10),
|
||||
args.get_str(&["-ut", "--udp-target"], default_udp_host_target).to_owned(),
|
||||
args.get(&["-st", "--socket-timeout"], default_socket_timeout),
|
||||
);
|
||||
|
||||
println!(
|
||||
|
@ -1,21 +1,62 @@
|
||||
use std::env;
|
||||
use wireguard_proxy::{Args, ProxyClient};
|
||||
use wireguard_proxy::{Args, ProxyClient, ProxyServer};
|
||||
|
||||
fn main() {
|
||||
let raw_args = env::args().collect();
|
||||
let args = Args::new(&raw_args);
|
||||
if args.get_str(1, "").contains("-h") {
|
||||
println!(
|
||||
"usage: {} [-h] [udp_host, 127.0.0.1:51820] [tcp_target, 127.0.0.1:5555] [socket_timeout, 0]",
|
||||
args.get_str(0, "wireguard-proxy")
|
||||
);
|
||||
|
||||
let default_udp_host_target = "127.0.0.1:51820";
|
||||
let default_socket_timeout = 0;
|
||||
|
||||
let tcp_target = args.get_option(&["-tt", "--tcp-target"]);
|
||||
let tcp_host = args.get_option(&["-th", "--tcp-host"]);
|
||||
|
||||
if args.flag("-h") || args.flag("--help") ||
|
||||
// one of them must be set
|
||||
(tcp_target.is_none() && tcp_host.is_none()) ||
|
||||
// but both cannot be set
|
||||
(tcp_target.is_some() && tcp_host.is_some())
|
||||
{
|
||||
println!(r#"usage: wireguard-proxy [options...]
|
||||
Client Mode (requires --tcp-target):
|
||||
-tt, --tcp-target <ip:port> TCP target to send packets to, where
|
||||
wireguard-proxy server is running
|
||||
-uh, --udp-host <ip:port> UDP host to listen on, point wireguard
|
||||
client here, default: {}
|
||||
|
||||
Server Mode (requires --tcp-host):
|
||||
-th, --tcp-host <ip:port> TCP host to listen on
|
||||
-ut, --udp-target <ip:port> UDP target to send packets to, where
|
||||
wireguard server is running,
|
||||
default: {}
|
||||
-ur, --udp-bind-host-range <ip:low-high> UDP host and port range to bind to,
|
||||
one port per TCP connection, to
|
||||
listen on for UDP packets to send
|
||||
back over the TCP connection,
|
||||
default: 127.0.0.1:30000-40000
|
||||
|
||||
Common Options:
|
||||
-h, --help print this usage text
|
||||
-st, --socket-timeout <seconds> Socket timeout (time to wait for data)
|
||||
before terminating, default: {}
|
||||
"#, default_udp_host_target, default_udp_host_target, default_socket_timeout);
|
||||
return;
|
||||
}
|
||||
|
||||
let socket_timeout = args.get(&["-st", "--socket-timeout"], default_socket_timeout);
|
||||
|
||||
if tcp_target.is_some() {
|
||||
client(tcp_target.unwrap(), socket_timeout, args);
|
||||
} else {
|
||||
server(tcp_host.unwrap(), socket_timeout, args);
|
||||
}
|
||||
}
|
||||
|
||||
fn client(tcp_target: &str, socket_timeout: u64, args: Args) {
|
||||
let proxy_client = ProxyClient::new(
|
||||
args.get_str(1, "127.0.0.1:51820").to_owned(),
|
||||
args.get_str(2, "127.0.0.1:5555").to_owned(),
|
||||
args.get(3, 0),
|
||||
args.get_str(&["-uh", "--udp-host"], "127.0.0.1:51820").to_owned(),
|
||||
tcp_target.to_owned(),
|
||||
socket_timeout,
|
||||
);
|
||||
|
||||
println!(
|
||||
@ -27,3 +68,45 @@ fn main() {
|
||||
|
||||
proxy_client.start().expect("error running proxy_client");
|
||||
}
|
||||
|
||||
fn server(tcp_host: &str, socket_timeout: u64, args: Args) {
|
||||
let udp_bind_host_range_str = args.get_str(&["-ur", "--udp-bind-host-range"], "127.0.0.1:30000-40000");
|
||||
let mut udp_bind_host_range = udp_bind_host_range_str.split(":");
|
||||
let udp_host = udp_bind_host_range
|
||||
.next()
|
||||
.expect("udp_bind_host_range host invalid");
|
||||
let mut udp_ports = udp_bind_host_range
|
||||
.next()
|
||||
.expect("udp_bind_host_range port range invalid")
|
||||
.split("-");
|
||||
let udp_low_port = udp_ports
|
||||
.next()
|
||||
.expect("udp_bind_host_range low port invalid")
|
||||
.trim()
|
||||
.parse::<u16>()
|
||||
.expect("udp_bind_host_range low port invalid");
|
||||
let udp_high_port = udp_ports
|
||||
.next()
|
||||
.expect("udp_bind_host_range low port invalid")
|
||||
.trim()
|
||||
.parse::<u16>()
|
||||
.expect("udp_bind_host_range low port invalid");
|
||||
|
||||
let proxy_server = ProxyServer::new(
|
||||
tcp_host.to_owned(),
|
||||
args.get_str(&["-ut", "--udp-target"], "127.0.0.1:51820").to_owned(),
|
||||
udp_host.to_string(),
|
||||
udp_low_port,
|
||||
udp_high_port,
|
||||
socket_timeout,
|
||||
);
|
||||
|
||||
println!(
|
||||
"udp_target: {}, udp_bind_host_range: {}, socket_timeout: {:?}",
|
||||
proxy_server.client_handler.udp_target,
|
||||
udp_bind_host_range_str,
|
||||
proxy_server.client_handler.socket_timeout,
|
||||
);
|
||||
|
||||
proxy_server.start().expect("error running proxy_server");
|
||||
}
|
||||
|
@ -1,54 +0,0 @@
|
||||
use std::env;
|
||||
use wireguard_proxy::{Args, ProxyServer};
|
||||
|
||||
fn main() {
|
||||
let raw_args = env::args().collect();
|
||||
let args = Args::new(&raw_args);
|
||||
if args.get_str(1, "").contains("-h") {
|
||||
println!(
|
||||
"usage: {} [-h] [tcp_host, 127.0.0.1:5555] [udp_target, 127.0.0.1:51820] [udp_bind_host_range, 127.0.0.1:30000-40000] [socket_timeout, 0]",
|
||||
args.get_str(0, "wireguard-proxyd")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let udp_bind_host_range_str = args.get_str(3, "127.0.0.1:30000-40000");
|
||||
let mut udp_bind_host_range = udp_bind_host_range_str.split(":");
|
||||
let udp_host = udp_bind_host_range
|
||||
.next()
|
||||
.expect("udp_bind_host_range host invalid");
|
||||
let mut udp_ports = udp_bind_host_range
|
||||
.next()
|
||||
.expect("udp_bind_host_range port range invalid")
|
||||
.split("-");
|
||||
let udp_low_port = udp_ports
|
||||
.next()
|
||||
.expect("udp_bind_host_range low port invalid")
|
||||
.trim()
|
||||
.parse::<u16>()
|
||||
.expect("udp_bind_host_range low port invalid");
|
||||
let udp_high_port = udp_ports
|
||||
.next()
|
||||
.expect("udp_bind_host_range low port invalid")
|
||||
.trim()
|
||||
.parse::<u16>()
|
||||
.expect("udp_bind_host_range low port invalid");
|
||||
|
||||
let proxy_server = ProxyServer::new(
|
||||
args.get_str(1, "127.0.0.1:5555").to_owned(),
|
||||
args.get_str(2, "127.0.0.1:51820").to_owned(),
|
||||
udp_host.to_string(),
|
||||
udp_low_port,
|
||||
udp_high_port,
|
||||
args.get(4, 0),
|
||||
);
|
||||
|
||||
println!(
|
||||
"udp_target: {}, udp_bind_host_range: {}, socket_timeout: {:?}",
|
||||
proxy_server.client_handler.udp_target,
|
||||
udp_bind_host_range_str,
|
||||
proxy_server.client_handler.socket_timeout,
|
||||
);
|
||||
|
||||
proxy_server.start().expect("error running proxy_server");
|
||||
}
|
31
src/lib.rs
31
src/lib.rs
@ -13,14 +13,31 @@ impl<'a> Args<'a> {
|
||||
pub fn new(args: &'a Vec<String>) -> Args {
|
||||
Args { args }
|
||||
}
|
||||
pub fn get_str(&self, index: usize, def: &'a str) -> &'a str {
|
||||
match self.args.get(index) {
|
||||
pub fn flag(&self, flag: &'a str) -> bool {
|
||||
self.args.contains(&flag.to_owned())
|
||||
}
|
||||
pub fn get_option(&self, flags: &[&'a str]) -> Option<&'a str> {
|
||||
for flag in flags.iter() {
|
||||
let mut found = false;
|
||||
for arg in self.args.iter() {
|
||||
if found {
|
||||
return Some(arg);
|
||||
}
|
||||
if arg == flag {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
pub fn get_str(&self, flags: &[&'a str], def: &'a str) -> &'a str {
|
||||
match self.get_option(flags) {
|
||||
Some(ret) => ret,
|
||||
None => def,
|
||||
}
|
||||
}
|
||||
pub fn get<T: FromStr>(&self, index: usize, def: T) -> T {
|
||||
match self.args.get(index) {
|
||||
pub fn get<T: FromStr>(&self, flags: &[&'a str], def: T) -> T {
|
||||
match self.get_option(flags) {
|
||||
Some(ret) => match ret.parse::<T>() {
|
||||
Ok(ret) => ret,
|
||||
Err(_) => def, // or panic
|
||||
@ -28,6 +45,12 @@ impl<'a> Args<'a> {
|
||||
None => def,
|
||||
}
|
||||
}
|
||||
pub fn get_str_idx(&self, index: usize, def: &'a str) -> &'a str {
|
||||
match self.args.get(index) {
|
||||
Some(ret) => ret,
|
||||
None => def,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TcpUdpPipe {
|
||||
|
17
test.sh
17
test.sh
@ -1,29 +1,32 @@
|
||||
#!/bin/sh
|
||||
set -x
|
||||
|
||||
# always run this clean
|
||||
cargo clean
|
||||
|
||||
# first make sure udp-test succeeds running against itself
|
||||
cargo run --release --bin udp-test || exit 1
|
||||
|
||||
# now run udp-test without spawning other processes
|
||||
cargo run --release --bin udp-test -- -is || exit 1
|
||||
|
||||
# now run udp-test essentially just like the script below, but all in rust
|
||||
cargo run --release --bin udp-test -- -s || exit 1
|
||||
|
||||
# now run proxyd pointing to udp-test
|
||||
cargo run --release --bin wireguard-proxyd -- 127.0.0.1:5555 127.0.0.1:51822 &
|
||||
cargo run --release --bin wireguard-proxy -- -th 127.0.0.1:5555 -ut 127.0.0.1:51822 &
|
||||
proxyd_pid=$!
|
||||
# wait for ports to be set up, this is fragile...
|
||||
sleep 1
|
||||
# proxy pointing to proxyd
|
||||
cargo run --release --bin wireguard-proxy &
|
||||
cargo run --release --bin wireguard-proxy -- -tt 127.0.0.1:5555 &
|
||||
proxy_pid=$!
|
||||
# wait for ports to be set up, this is fragile...
|
||||
sleep 1
|
||||
# and udp-test pointing to proxy, which then hops to proxyd, and finally back to udp-test
|
||||
cargo run --release --bin udp-test -- 127.0.0.1:51822
|
||||
cargo run --release --bin udp-test -- -uh 127.0.0.1:51822
|
||||
udp_exit=$?
|
||||
|
||||
kill $proxyd_pid $proxy_pid
|
||||
|
||||
exit $udp_exit
|
||||
[ $udp_exit -ne 0 ] && exit $udp_exit
|
||||
|
||||
# now run udp-test essentially just like the script above, but all in rust
|
||||
cargo run --release --bin udp-test -- -s
|
||||
|
Loading…
Reference in New Issue
Block a user