mirror of https://github.com/dswd/vpncloud.git
Almost works
This commit is contained in:
parent
d50490ac51
commit
124f7cbff9
|
@ -824,7 +824,7 @@ impl<D: Device, P: Protocol, S: Socket, TS: TimeSource> GenericCloud<D, P, S, TS
|
||||||
/// Also, this method will call `housekeep` every second.
|
/// Also, this method will call `housekeep` every second.
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
let ctrlc = CtrlC::new();
|
let ctrlc = CtrlC::new();
|
||||||
let waiter = try_fail!(WaitImpl::new(&self.socket, &self.device, 1000), "Failed to setup poll: {}");
|
let waiter = try_fail!(WaitImpl::new(self.socket.as_raw_fd(), self.device.as_raw_fd(), 1000), "Failed to setup poll: {}");
|
||||||
let mut buffer = MsgBuffer::new(SPACE_BEFORE);
|
let mut buffer = MsgBuffer::new(SPACE_BEFORE);
|
||||||
let mut poll_error = false;
|
let mut poll_error = false;
|
||||||
for evt in waiter {
|
for evt in waiter {
|
||||||
|
|
|
@ -303,7 +303,7 @@ fn main() {
|
||||||
error!("Either password or private key must be set in config or given as parameter");
|
error!("Either password or private key must be set in config or given as parameter");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if config.listen.starts_with("ws") {
|
if config.listen.starts_with("ws://") {
|
||||||
let socket = try_fail!(ProxyConnection::listen(&config.listen), "Failed to open socket {}: {}", config.listen);
|
let socket = try_fail!(ProxyConnection::listen(&config.listen), "Failed to open socket {}: {}", config.listen);
|
||||||
match config.device_type {
|
match config.device_type {
|
||||||
Type::Tap => run::<payload::Frame, _>(config, socket),
|
Type::Tap => run::<payload::Frame, _>(config, socket),
|
||||||
|
|
|
@ -2,11 +2,9 @@
|
||||||
// Copyright (C) 2015-2020 Dennis Schwerdel
|
// Copyright (C) 2015-2020 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use crate::device::Device;
|
|
||||||
use std::{io, os::unix::io::RawFd};
|
use std::{io, os::unix::io::RawFd};
|
||||||
|
|
||||||
use super::WaitResult;
|
use super::WaitResult;
|
||||||
use crate::net::Socket;
|
|
||||||
|
|
||||||
pub struct EpollWait {
|
pub struct EpollWait {
|
||||||
poll_fd: RawFd,
|
poll_fd: RawFd,
|
||||||
|
@ -17,21 +15,21 @@ pub struct EpollWait {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EpollWait {
|
impl EpollWait {
|
||||||
pub fn new<S: Socket>(socket: &S, device: &dyn Device, timeout: u32) -> io::Result<Self> {
|
pub fn new(socket: RawFd, device: RawFd, timeout: u32) -> io::Result<Self> {
|
||||||
Self::create(socket, device, timeout, libc::EPOLLIN as u32)
|
Self::create(socket, device, timeout, libc::EPOLLIN as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn testing<S: Socket>(socket: &S, device: &dyn Device, timeout: u32) -> io::Result<Self> {
|
pub fn testing(socket: RawFd, device: RawFd, timeout: u32) -> io::Result<Self> {
|
||||||
Self::create(socket, device, timeout, (libc::EPOLLIN | libc::EPOLLOUT) as u32)
|
Self::create(socket, device, timeout, (libc::EPOLLIN | libc::EPOLLOUT) as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create<S: Socket>(socket: &S, device: &dyn Device, timeout: u32, flags: u32) -> io::Result<Self> {
|
fn create(socket: RawFd, device: RawFd, timeout: u32, flags: u32) -> io::Result<Self> {
|
||||||
let mut event = libc::epoll_event { u64: 0, events: 0 };
|
let mut event = libc::epoll_event { u64: 0, events: 0 };
|
||||||
let poll_fd = unsafe { libc::epoll_create(3) };
|
let poll_fd = unsafe { libc::epoll_create(3) };
|
||||||
if poll_fd == -1 {
|
if poll_fd == -1 {
|
||||||
return Err(io::Error::last_os_error())
|
return Err(io::Error::last_os_error())
|
||||||
}
|
}
|
||||||
for fd in &[socket.as_raw_fd(), device.as_raw_fd()] {
|
for fd in &[socket, device] {
|
||||||
event.u64 = *fd as u64;
|
event.u64 = *fd as u64;
|
||||||
event.events = flags;
|
event.events = flags;
|
||||||
let res = unsafe { libc::epoll_ctl(poll_fd, libc::EPOLL_CTL_ADD, *fd, &mut event) };
|
let res = unsafe { libc::epoll_ctl(poll_fd, libc::EPOLL_CTL_ADD, *fd, &mut event) };
|
||||||
|
@ -39,7 +37,7 @@ impl EpollWait {
|
||||||
return Err(io::Error::last_os_error())
|
return Err(io::Error::last_os_error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Self { poll_fd, event, socket: socket.as_raw_fd(), device: device.as_raw_fd(), timeout })
|
Ok(Self { poll_fd, event, socket, device, timeout })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
152
src/wsproxy.rs
152
src/wsproxy.rs
|
@ -1,42 +1,125 @@
|
||||||
use super::{
|
use super::{
|
||||||
net::{mapped_addr, Socket},
|
net::{mapped_addr, Socket},
|
||||||
|
poll::{WaitImpl, WaitResult},
|
||||||
port_forwarding::PortForwarding,
|
port_forwarding::PortForwarding,
|
||||||
util::MsgBuffer
|
util::MsgBuffer
|
||||||
};
|
};
|
||||||
use std::{
|
|
||||||
io::{self, Write, Read, Cursor},
|
|
||||||
net::{SocketAddr, TcpListener, SocketAddrV6, Ipv6Addr},
|
|
||||||
os::unix::io::{AsRawFd, RawFd},
|
|
||||||
thread::spawn,
|
|
||||||
};
|
|
||||||
use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
|
||||||
|
use std::{
|
||||||
|
io::{self, Cursor, Read, Write},
|
||||||
|
net::{Ipv6Addr, SocketAddr, SocketAddrV6, TcpListener, TcpStream, UdpSocket},
|
||||||
|
os::unix::io::{AsRawFd, RawFd},
|
||||||
|
thread::spawn
|
||||||
|
};
|
||||||
use tungstenite::{client::AutoStream, connect, protocol::WebSocket, server::accept, stream::Stream, Message};
|
use tungstenite::{client::AutoStream, connect, protocol::WebSocket, server::accept, stream::Stream, Message};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub fn run_proxy() {
|
|
||||||
let server = TcpListener::bind("127.0.0.1:9001").unwrap();
|
macro_rules! io_error {
|
||||||
for stream in server.incoming() {
|
($val:expr, $format:expr) => ( {
|
||||||
info!("connect");
|
$val.map_err(|err| io::Error::new(io::ErrorKind::Other, format!($format, err)))
|
||||||
spawn(move || {
|
} );
|
||||||
let mut websocket = accept(stream.unwrap()).unwrap();
|
($val:expr, $format:expr, $( $arg:expr ),+) => ( {
|
||||||
loop {
|
$val.map_err(|err| io::Error::new(io::ErrorKind::Other, format!($format, $( $arg ),+, err)))
|
||||||
let msg = websocket.read_message().unwrap();
|
} );
|
||||||
// We do not want to send back ping/pong messages.
|
}
|
||||||
if msg.is_binary() || msg.is_text() {
|
|
||||||
info!("msg");
|
fn write_addr<W: Write>(addr: SocketAddr, mut out: W) -> Result<(), io::Error> {
|
||||||
websocket.write_message(msg).unwrap();
|
let addr = mapped_addr(addr);
|
||||||
|
match mapped_addr(addr) {
|
||||||
|
SocketAddr::V6(addr) => {
|
||||||
|
out.write_all(&addr.ip().octets())?;
|
||||||
|
out.write_u16::<NetworkEndian>(addr.port())?;
|
||||||
}
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_addr<R: Read>(mut r: R) -> Result<SocketAddr, io::Error> {
|
||||||
|
let mut ip = [0u8; 16];
|
||||||
|
r.read_exact(&mut ip)?;
|
||||||
|
let port = r.read_u16::<NetworkEndian>()?;
|
||||||
|
let addr = SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(ip), port, 0, 0));
|
||||||
|
Ok(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serve_proxy_connection(stream: TcpStream) -> Result<(), io::Error> {
|
||||||
|
let peer = stream.peer_addr()?;
|
||||||
|
info!("WS client {} connected", peer);
|
||||||
|
let mut websocket = io_error!(accept(stream), "Failed to initialize websocket with {}: {}", peer)?;
|
||||||
|
let udpsocket = UdpSocket::bind("[::]:0")?;
|
||||||
|
let mut msg = Vec::with_capacity(18);
|
||||||
|
let addr = udpsocket.local_addr()?;
|
||||||
|
info!("Listening on {} for peer {}", addr, peer);
|
||||||
|
write_addr(addr, &mut msg)?;
|
||||||
|
io_error!(websocket.write_message(Message::Binary(msg)), "Failed to write to ws connection: {}")?;
|
||||||
|
let websocketfd = websocket.get_ref().as_raw_fd();
|
||||||
|
let poll = WaitImpl::new(websocketfd, udpsocket.as_raw_fd(), 60)?;
|
||||||
|
let mut buffer = [0; 65535];
|
||||||
|
for evt in poll {
|
||||||
|
match evt {
|
||||||
|
WaitResult::Socket => {
|
||||||
|
info!("WS -> UDP");
|
||||||
|
let msg = io_error!(websocket.read_message(), "Failed to read message on websocket {}: {}", peer)?;
|
||||||
|
info!("MSG: {}", msg);
|
||||||
|
match msg {
|
||||||
|
Message::Binary(data) => {
|
||||||
|
let dst = read_addr(Cursor::new(&data))?;
|
||||||
|
udpsocket.send_to(&data[18..], dst)?;
|
||||||
|
}
|
||||||
|
Message::Close(_) => return Ok(()),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WaitResult::Device => {
|
||||||
|
info!("UDP -> WS");
|
||||||
|
let (size, addr) = udpsocket.recv_from(&mut buffer)?;
|
||||||
|
let mut data = Vec::with_capacity(18 + size);
|
||||||
|
write_addr(addr, &mut data)?;
|
||||||
|
data.write_all(&buffer[..size])?;
|
||||||
|
io_error!(websocket.write_message(Message::Binary(data)), "Failed to write to {}: {}", peer)?;
|
||||||
|
}
|
||||||
|
WaitResult::Timeout => {
|
||||||
|
info!("Sending ping");
|
||||||
|
io_error!(websocket.write_message(Message::Ping(vec![])), "Failed to send ping: {}")?;
|
||||||
|
}
|
||||||
|
WaitResult::Error(err) => return Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_proxy() -> Result<(), io::Error> {
|
||||||
|
// TODO: configurable listen
|
||||||
|
let server = TcpListener::bind("127.0.0.1:9001")?;
|
||||||
|
for stream in server.incoming() {
|
||||||
|
let stream = stream?;
|
||||||
|
let peer = stream.peer_addr()?;
|
||||||
|
spawn(move || {
|
||||||
|
if let Err(err) = serve_proxy_connection(stream) {
|
||||||
|
error!("Error on connection {}: {}", peer, err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ProxyConnection {
|
pub struct ProxyConnection {
|
||||||
url: String,
|
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
socket: WebSocket<AutoStream>
|
socket: WebSocket<AutoStream>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ProxyConnection {
|
||||||
|
fn read_message(&mut self) -> Result<Vec<u8>, io::Error> {
|
||||||
|
loop {
|
||||||
|
if let Message::Binary(data) = io_error!(self.socket.read_message(), "Failed to read from ws proxy: {}")? {
|
||||||
|
return Ok(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AsRawFd for ProxyConnection {
|
impl AsRawFd for ProxyConnection {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
match self.socket.get_ref() {
|
match self.socket.get_ref() {
|
||||||
|
@ -48,39 +131,28 @@ impl AsRawFd for ProxyConnection {
|
||||||
|
|
||||||
impl Socket for ProxyConnection {
|
impl Socket for ProxyConnection {
|
||||||
fn listen(url: &str) -> Result<Self, io::Error> {
|
fn listen(url: &str) -> Result<Self, io::Error> {
|
||||||
let (mut socket, _) = connect(Url::parse(url).unwrap()).unwrap();
|
let parsed_url = io_error!(Url::parse(url), "Invalid URL {}: {}", url)?;
|
||||||
|
let (socket, _) = io_error!(connect(parsed_url), "Failed to connect to URL {}: {}", url)?;
|
||||||
let addr = "0.0.0.0:0".parse::<SocketAddr>().unwrap();
|
let addr = "0.0.0.0:0".parse::<SocketAddr>().unwrap();
|
||||||
Ok(ProxyConnection { url: addr.to_string(), addr, socket })
|
let mut con = ProxyConnection { addr, socket };
|
||||||
|
let addr_data = con.read_message()?;
|
||||||
|
con.addr = read_addr(Cursor::new(&addr_data))?;
|
||||||
|
Ok(con)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive(&mut self, buffer: &mut MsgBuffer) -> Result<SocketAddr, io::Error> {
|
fn receive(&mut self, buffer: &mut MsgBuffer) -> Result<SocketAddr, io::Error> {
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
match self.socket.read_message().unwrap() {
|
let data = self.read_message()?;
|
||||||
Message::Binary(data) => {
|
let addr = read_addr(Cursor::new(&data))?;
|
||||||
let mut cursor = Cursor::new(&data);
|
|
||||||
let mut ip = [0u8; 16];
|
|
||||||
cursor.read_exact(&mut ip)?;
|
|
||||||
let port = cursor.read_u16::<NetworkEndian>()?;
|
|
||||||
let addr = SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(ip), port, 0, 0));
|
|
||||||
buffer.clone_from(&data[18..]);
|
buffer.clone_from(&data[18..]);
|
||||||
Ok(addr)
|
Ok(addr)
|
||||||
},
|
|
||||||
_ => unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send(&mut self, data: &[u8], addr: SocketAddr) -> Result<usize, io::Error> {
|
fn send(&mut self, data: &[u8], addr: SocketAddr) -> Result<usize, io::Error> {
|
||||||
let mut msg = Vec::with_capacity(data.len() + 18);
|
let mut msg = Vec::with_capacity(data.len() + 18);
|
||||||
let addr = mapped_addr(addr);
|
write_addr(addr, &mut msg)?;
|
||||||
match mapped_addr(addr) {
|
|
||||||
SocketAddr::V6(addr) => {
|
|
||||||
msg.write_all(&addr.ip().octets())?;
|
|
||||||
msg.write_u16::<NetworkEndian>(addr.port())?;
|
|
||||||
},
|
|
||||||
_ => unreachable!()
|
|
||||||
}
|
|
||||||
msg.write_all(data)?;
|
msg.write_all(data)?;
|
||||||
self.socket.write_message(Message::Binary(msg)).unwrap();
|
io_error!(self.socket.write_message(Message::Binary(msg)), "Failed to write to ws proxy: {}")?;
|
||||||
Ok(data.len())
|
Ok(data.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue