First (unsafe) go at tls support
This commit is contained in:
parent
5280c038b7
commit
4c6f4258b4
@ -130,4 +130,5 @@ branches:
|
||||
- master
|
||||
- travis
|
||||
- ci
|
||||
- openssl
|
||||
|
||||
|
94
Cargo.lock
generated
94
Cargo.lock
generated
@ -1,6 +1,100 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wireguard-proxy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
"checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
|
||||
"checksum openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585"
|
||||
"checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f"
|
||||
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||
"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
|
||||
|
@ -18,3 +18,10 @@ include = [
|
||||
"LICENSE-*",
|
||||
"*.md",
|
||||
]
|
||||
|
||||
[features]
|
||||
default = ["tls"]
|
||||
tls = ["openssl"]
|
||||
|
||||
[dependencies]
|
||||
openssl = { version = "0.10.26", optional = true }
|
||||
|
@ -84,6 +84,7 @@ branches:
|
||||
- master
|
||||
- appveyor
|
||||
- ci
|
||||
- openssl
|
||||
|
||||
notifications:
|
||||
- provider: Email
|
||||
|
@ -23,6 +23,8 @@ fn main() {
|
||||
wireguard-proxy server is running
|
||||
-uh, --udp-host <ip:port> UDP host to listen on, point wireguard
|
||||
client here, default: {}
|
||||
--tls use TLS when connecting to tcp-target
|
||||
WARNING: currently verifies nothing!
|
||||
|
||||
Server Mode (requires --tcp-host):
|
||||
-th, --tcp-host <ip:port> TCP host to listen on
|
||||
@ -66,7 +68,11 @@ fn client(tcp_target: &str, socket_timeout: u64, args: Args) {
|
||||
proxy_client.socket_timeout,
|
||||
);
|
||||
|
||||
proxy_client.start().expect("error running proxy_client");
|
||||
if args.flag("--tls") {
|
||||
proxy_client.start_tls().expect("error running tls proxy_client");
|
||||
} else {
|
||||
proxy_client.start().expect("error running proxy_client");
|
||||
}
|
||||
}
|
||||
|
||||
fn server(tcp_host: &str, socket_timeout: u64, args: Args) {
|
||||
|
152
src/lib.rs
152
src/lib.rs
@ -4,6 +4,8 @@ use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::cell::{UnsafeCell};
|
||||
use openssl::ssl::{SslConnector, SslMethod, SslStream, SslVerifyMode};
|
||||
|
||||
pub struct Args<'a> {
|
||||
args: &'a Vec<String>,
|
||||
@ -53,14 +55,14 @@ impl<'a> Args<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TcpUdpPipe {
|
||||
pub struct TcpUdpPipe<T: Write + Read + TryClone<T> + Send + 'static> {
|
||||
buf: [u8; 2050], // 2048 + 2 for len
|
||||
tcp_stream: TcpStream,
|
||||
tcp_stream: T,
|
||||
udp_socket: UdpSocket,
|
||||
}
|
||||
|
||||
impl TcpUdpPipe {
|
||||
pub fn new(tcp_stream: TcpStream, udp_socket: UdpSocket) -> TcpUdpPipe {
|
||||
impl<T: Write + Read + TryClone<T> + Send + 'static> TcpUdpPipe<T> {
|
||||
pub fn new(tcp_stream: T, udp_socket: UdpSocket) -> TcpUdpPipe<T> {
|
||||
TcpUdpPipe {
|
||||
tcp_stream,
|
||||
udp_socket,
|
||||
@ -68,28 +70,30 @@ impl TcpUdpPipe {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_clone(&self) -> std::io::Result<TcpUdpPipe> {
|
||||
pub fn try_clone(&self) -> std::io::Result<TcpUdpPipe<T>> {
|
||||
Ok(TcpUdpPipe::new(
|
||||
self.tcp_stream.try_clone()?,
|
||||
self.udp_socket.try_clone()?,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn udp_to_tcp_connect_socket(&mut self) -> std::io::Result<usize> {
|
||||
pub fn shuffle_after_first_udp(&mut self) -> std::io::Result<usize> {
|
||||
let (len, src_addr) = self.udp_socket.recv_from(&mut self.buf[2..])?;
|
||||
|
||||
println!("first packet from {}, connecting to that", src_addr);
|
||||
self.udp_socket.connect(src_addr)?;
|
||||
|
||||
self.send_udp(len)
|
||||
self.send_udp(len)?;
|
||||
|
||||
self.shuffle()
|
||||
}
|
||||
|
||||
pub fn udp_to_tcp(&mut self) -> std::io::Result<usize> {
|
||||
pub fn udp_to_tcp(&mut self) -> std::io::Result<()> {
|
||||
let len = self.udp_socket.recv(&mut self.buf[2..])?;
|
||||
self.send_udp(len)
|
||||
}
|
||||
|
||||
fn send_udp(&mut self, len: usize) -> std::io::Result<usize> {
|
||||
fn send_udp(&mut self, len: usize) -> std::io::Result<()> {
|
||||
println!("udp got len: {}", len);
|
||||
|
||||
self.buf[0] = ((len >> 8) & 0xFF) as u8;
|
||||
@ -98,7 +102,8 @@ impl TcpUdpPipe {
|
||||
//let test_len = ((self.buf[0] as usize) << 8) + self.buf[1] as usize;
|
||||
//println!("tcp sending test_len: {}", test_len);
|
||||
|
||||
self.tcp_stream.write(&self.buf[..len + 2])
|
||||
self.tcp_stream.write_all(&self.buf[..len + 2])
|
||||
// todo: do this? self.tcp_stream.flush()
|
||||
}
|
||||
|
||||
pub fn tcp_to_udp(&mut self) -> std::io::Result<usize> {
|
||||
@ -112,6 +117,19 @@ impl TcpUdpPipe {
|
||||
//let sent = udp_socket.send_to(&buf[..len], &self.udp_target)?;
|
||||
//assert_eq!(sent, len);
|
||||
}
|
||||
|
||||
pub fn shuffle(&mut self) -> std::io::Result<usize> {
|
||||
let mut udp_pipe_clone = self.try_clone()?;
|
||||
thread::spawn(move || loop {
|
||||
udp_pipe_clone
|
||||
.udp_to_tcp()
|
||||
.expect("cannot write to tcp_clone");
|
||||
});
|
||||
|
||||
loop {
|
||||
self.tcp_to_udp()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ProxyClient {
|
||||
@ -132,32 +150,110 @@ impl ProxyClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&self) -> std::io::Result<usize> {
|
||||
fn tcp_connect(&self) -> std::io::Result<TcpStream> {
|
||||
let tcp_stream = TcpStream::connect(&self.tcp_target)?;
|
||||
|
||||
tcp_stream.set_read_timeout(self.socket_timeout)?;
|
||||
Ok(tcp_stream)
|
||||
}
|
||||
|
||||
fn udp_connect(&self) -> std::io::Result<UdpSocket> {
|
||||
let udp_socket = UdpSocket::bind(&self.udp_host)?;
|
||||
udp_socket.set_read_timeout(self.socket_timeout)?;
|
||||
Ok(udp_socket)
|
||||
}
|
||||
|
||||
let mut udp_pipe = TcpUdpPipe::new(tcp_stream, udp_socket);
|
||||
pub fn start(&self) -> std::io::Result<usize> {
|
||||
let tcp_stream = self.tcp_connect()?;
|
||||
|
||||
let udp_socket = self.udp_connect()?;
|
||||
|
||||
// we want to wait for first udp packet from client first, to set the target to respond to
|
||||
udp_pipe.udp_to_tcp_connect_socket()?;
|
||||
TcpUdpPipe::new(tcp_stream, udp_socket).shuffle_after_first_udp()
|
||||
}
|
||||
|
||||
let mut udp_pipe_clone = udp_pipe.try_clone()?;
|
||||
thread::spawn(move || loop {
|
||||
udp_pipe_clone
|
||||
.udp_to_tcp()
|
||||
.expect("cannot write to tcp_clone");
|
||||
});
|
||||
pub fn start_tls(&self) -> std::io::Result<usize> {
|
||||
let tcp_stream = self.tcp_connect()?;
|
||||
|
||||
loop {
|
||||
udp_pipe.tcp_to_udp()?;
|
||||
let mut connector = SslConnector::builder(SslMethod::tls()).unwrap().build().configure().unwrap();
|
||||
connector.set_verify_hostname(false);
|
||||
connector.set_verify(SslVerifyMode::NONE);
|
||||
let tcp_stream = connector.connect(self.tcp_target.split(":").next().unwrap(), tcp_stream).unwrap();
|
||||
let tcp_stream = OpensslCell { sess: Arc::new(UnsafeCell::new(tcp_stream)) };
|
||||
|
||||
let udp_socket = self.udp_connect()?;
|
||||
|
||||
// we want to wait for first udp packet from client first, to set the target to respond to
|
||||
TcpUdpPipe::new(tcp_stream, udp_socket).shuffle_after_first_udp()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait TryClone<T> {
|
||||
fn try_clone(&self) -> std::io::Result<T>;
|
||||
}
|
||||
|
||||
impl TryClone<UdpSocket> for UdpSocket {
|
||||
fn try_clone(&self) -> std::io::Result<UdpSocket> {
|
||||
self.try_clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryClone<TcpStream> for TcpStream {
|
||||
fn try_clone(&self) -> std::io::Result<TcpStream> {
|
||||
self.try_clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryClone<OpensslCell> for OpensslCell {
|
||||
fn try_clone(&self) -> std::io::Result<OpensslCell> {
|
||||
Ok(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OpensslCell {
|
||||
sess: Arc<UnsafeCell<SslStream<TcpStream>>>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for OpensslCell {}
|
||||
unsafe impl Send for OpensslCell {}
|
||||
|
||||
impl Clone for OpensslCell {
|
||||
fn clone(&self) -> Self {
|
||||
OpensslCell {
|
||||
sess: self.sess.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OpensslCell {
|
||||
pub fn borrow(&self) -> &SslStream<TcpStream> {
|
||||
unsafe {
|
||||
&*self.sess.get()
|
||||
}
|
||||
}
|
||||
pub fn borrow_mut(&self) -> &mut SslStream<TcpStream> {
|
||||
unsafe {
|
||||
&mut *self.sess.get()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for OpensslCell {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
|
||||
self.borrow_mut().read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for OpensslCell {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
|
||||
self.borrow_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Result<(), std::io::Error> {
|
||||
self.borrow_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ProxyServer {
|
||||
pub tcp_host: String,
|
||||
pub client_handler: Arc<ProxyServerClientHandler>,
|
||||
@ -238,16 +334,6 @@ impl ProxyServerClientHandler {
|
||||
udp_socket.set_read_timeout(self.socket_timeout)?;
|
||||
udp_socket.connect(&self.udp_target)?;
|
||||
|
||||
let mut udp_pipe = TcpUdpPipe::new(tcp_stream, udp_socket);
|
||||
let mut udp_pipe_clone = udp_pipe.try_clone()?;
|
||||
thread::spawn(move || loop {
|
||||
udp_pipe_clone
|
||||
.udp_to_tcp()
|
||||
.expect("cannot write to tcp_clone");
|
||||
});
|
||||
|
||||
loop {
|
||||
udp_pipe.tcp_to_udp()?;
|
||||
}
|
||||
TcpUdpPipe::new(tcp_stream, udp_socket).shuffle()
|
||||
}
|
||||
}
|
||||
|
10
test.sh
10
test.sh
@ -16,7 +16,13 @@ proxyd_pid=$!
|
||||
# wait for ports to be set up, this is fragile...
|
||||
sleep 1
|
||||
# proxy pointing to proxyd
|
||||
cargo run --release --bin wireguard-proxy -- -tt 127.0.0.1:5555 &
|
||||
#cargo run --release --bin wireguard-proxy -- -tt 127.0.0.1:5555 &
|
||||
|
||||
echo -e '\n\n\n\n\n\n\n' | openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.key
|
||||
socat OPENSSL-LISTEN:5554,bind=127.0.0.1,cert=./cert.pem,key=./cert.key,verify=0 tcp4-connect:127.0.0.1:5555 &
|
||||
|
||||
cargo run --release --bin wireguard-proxy -- -tt 127.0.0.1:5554 --tls &
|
||||
|
||||
proxy_pid=$!
|
||||
# wait for ports to be set up, this is fragile...
|
||||
sleep 1
|
||||
@ -26,6 +32,8 @@ udp_exit=$?
|
||||
|
||||
kill $proxyd_pid $proxy_pid
|
||||
|
||||
rm -f cert.pem cert.key
|
||||
|
||||
[ $udp_exit -ne 0 ] && exit $udp_exit
|
||||
|
||||
# now run udp-test essentially just like the script above, but all in rust
|
||||
|
Loading…
Reference in New Issue
Block a user