8 Commits

Author SHA1 Message Date
Datong Sun
c5a5116808 chore(phantun) bump to v0.2.3, bump fake-tcp dependency to v0.2.0 2021-11-18 20:37:28 -08:00
Datong Sun
e8f2457cb5 chore(fake-tcp) bump to v0.2.0 2021-11-18 20:36:05 -08:00
Datong Sun
583cdbe300 perf(fake-tcp) reduce the number of clone() calls in hot path 2021-11-19 12:35:21 +08:00
Datong Sun
91988520e5 feat(*) add DNS name support for --remote argument in both Client and
Server
2021-11-19 12:30:47 +08:00
Datong Sun
49cc6a6865 chore(phantun) update fake-tcp dependency version to v0.1.3 2021-11-02 18:29:53 +08:00
Datong Sun
7390d4bf27 chore(fake-tcp) release version v0.1.3 2021-11-02 18:29:53 +08:00
dependabot[bot]
95e762f5fd chore(deps): update dndx-fork-tokio-tun requirement from 0.3.16 to 0.4.0
Updates the requirements on [dndx-fork-tokio-tun](https://github.com/yaa110/tokio-tun) to permit the latest version.
- [Release notes](https://github.com/yaa110/tokio-tun/releases)
- [Commits](https://github.com/yaa110/tokio-tun/compare/0.3.16...0.4.0)

---
updated-dependencies:
- dependency-name: dndx-fork-tokio-tun
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-02 18:29:53 +08:00
Datong Sun
c9043015f2 docs(readme) update latest release to v0.2.2 2021-10-30 09:32:14 -07:00
6 changed files with 57 additions and 65 deletions

View File

@@ -31,7 +31,7 @@ Table of Contents
# Latest release
[v0.2.1](https://github.com/dndx/phantun/releases/tag/v0.2.1)
[v0.2.2](https://github.com/dndx/phantun/releases/tag/v0.2.2)
# Overview

View File

@@ -1,6 +1,6 @@
[package]
name = "fake-tcp"
version = "0.1.2"
version = "0.2.0"
edition = "2021"
authors = ["Datong Sun <dndx@idndx.com>"]
license = "MIT OR Apache-2.0"
@@ -21,4 +21,4 @@ tokio = { version = "1.12.0", features = ["full"] }
rand = { version = "0.8.4", features = ["small_rng"] }
log = "0.4"
internet-checksum = "0.2.0"
dndx-fork-tokio-tun = "0.3.16"
dndx-fork-tokio-tun = "0.4.0"

View File

@@ -15,7 +15,6 @@ use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::{Arc, RwLock};
use tokio::sync::broadcast;
use tokio::sync::mpsc::{self, Receiver, Sender};
use tokio::sync::watch;
use tokio::sync::Mutex as AsyncMutex;
use tokio::time;
use tokio_tun::Tun;
@@ -58,6 +57,7 @@ pub enum State {
SynSent,
SynReceived,
Established,
Closed,
}
pub struct Socket {
@@ -69,8 +69,6 @@ pub struct Socket {
seq: AtomicU32,
ack: AtomicU32,
state: State,
closing_tx: watch::Sender<()>,
closing_rx: watch::Receiver<()>,
}
impl Socket {
@@ -83,7 +81,6 @@ impl Socket {
state: State,
) -> (Socket, Sender<Bytes>) {
let (incoming_tx, incoming_rx) = mpsc::channel(MPSC_BUFFER_LEN);
let (closing_tx, closing_rx) = watch::channel(());
(
Socket {
@@ -95,8 +92,6 @@ impl Socket {
seq: AtomicU32::new(0),
ack: AtomicU32::new(ack.unwrap_or(0)),
state,
closing_tx,
closing_rx,
},
incoming_tx,
)
@@ -114,8 +109,6 @@ impl Socket {
}
pub async fn send(&self, payload: &[u8]) -> Option<()> {
let mut closing = self.closing_rx.clone();
match self.state {
State::Established => {
let buf = self.build_tcp_packet(tcp::TcpFlags::ACK, Some(payload));
@@ -126,53 +119,40 @@ impl Socket {
res.unwrap();
Some(())
},
_ = closing.changed() => {
None
}
}
}
State::Closed => None,
_ => unreachable!(),
}
}
pub async fn recv(&self, buf: &mut [u8]) -> Option<usize> {
let mut closing = self.closing_rx.clone();
match self.state {
State::Established => {
let mut incoming = self.incoming.lock().await;
tokio::select! {
Some(raw_buf) = incoming.recv() => {
let (_v4_packet, tcp_packet) = parse_ipv4_packet(&raw_buf);
incoming.recv().await.and_then(|raw_buf| {
let (_v4_packet, tcp_packet) = parse_ipv4_packet(&raw_buf);
if (tcp_packet.get_flags() & tcp::TcpFlags::RST) != 0 {
info!("Connection {} reset by peer", self);
self.close();
return None;
}
let payload = tcp_packet.payload();
self.ack
.store(tcp_packet.get_sequence().wrapping_add(1), Ordering::Relaxed);
buf[..payload.len()].copy_from_slice(payload);
Some(payload.len())
},
_ = closing.changed() => {
None
if (tcp_packet.get_flags() & tcp::TcpFlags::RST) != 0 {
info!("Connection {} reset by peer", self);
return None;
}
}
let payload = tcp_packet.payload();
self.ack
.store(tcp_packet.get_sequence().wrapping_add(1), Ordering::Relaxed);
buf[..payload.len()].copy_from_slice(payload);
Some(payload.len())
})
}
State::Closed => None,
_ => unreachable!(),
}
}
pub fn close(&self) {
self.closing_tx.send(()).unwrap();
}
async fn accept(mut self) {
for _ in 0..RETRIES {
match self.state {
@@ -272,6 +252,8 @@ impl Socket {
impl Drop for Socket {
fn drop(&mut self) {
self.state = State::Closed;
let tuple = AddrTuple::new(self.local_addr, self.remote_addr);
// dissociates ourself from the dispatch map
assert!(self.shared.tuples.write().unwrap().remove(&tuple).is_some());
@@ -282,7 +264,7 @@ impl Drop for Socket {
if let Err(e) = self.tun.try_send(&buf) {
warn!("Unable to send RST to remote end: {}", e);
}
self.close();
info!("Fake TCP connection to {} closed", self);
}
}
@@ -396,11 +378,10 @@ impl Stack {
} else {
trace!("Cache miss, checking the shared tuples table for connection");
let sender;
{
let sender = {
let tuples = shared.tuples.read().unwrap();
sender = tuples.get(&tuple).cloned();
}
tuples.get(&tuple).cloned()
};
if let Some(c) = sender {
trace!("Storing connection information into local tuples");

View File

@@ -1,6 +1,6 @@
[package]
name = "phantun"
version = "0.2.2"
version = "0.2.3"
edition = "2021"
authors = ["Datong Sun <dndx@idndx.com>"]
license = "MIT OR Apache-2.0"
@@ -13,9 +13,9 @@ Layer 3 & Layer 4 (NAPT) firewalls/NATs.
[dependencies]
clap = "2.33.3"
socket2 = { version = "0.4.2", features = ["all"] }
fake-tcp = "0.1.2"
fake-tcp = "0.2.0"
tokio = { version = "1.12.0", features = ["full"] }
log = "0.4"
pretty_env_logger = "0.4.0"
dndx-fork-tokio-tun = "0.3.16"
dndx-fork-tokio-tun = "0.4.0"
num_cpus = "1.13.0"

View File

@@ -6,7 +6,7 @@ use fake_tcp::{Socket, Stack};
use log::{debug, error, info};
use std::collections::HashMap;
use std::convert::TryInto;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::net::{Ipv4Addr, SocketAddr};
use std::sync::Arc;
use std::time::Duration;
use tokio::net::UdpSocket;
@@ -57,8 +57,8 @@ async fn main() {
.short("r")
.long("remote")
.required(true)
.value_name("IP:PORT")
.help("Sets the address and port where Phantun Client connects to Phantun Server")
.value_name("IP or HOST NAME:PORT")
.help("Sets the address or host name and port where Phantun Client connects to Phantun Server")
.takes_value(true),
)
.arg(
@@ -97,11 +97,19 @@ async fn main() {
.unwrap()
.parse()
.expect("bad local address");
let remote_addr: SocketAddrV4 = matches
.value_of("remote")
.unwrap()
.parse()
.expect("bad remote address");
let remote_addr = tokio::net::lookup_host(matches.value_of("remote").unwrap())
.await
.expect("bad remote address or host")
.next()
.expect("unable to resolve remote host name");
let remote_addr = if let SocketAddr::V4(addr) = remote_addr {
addr
} else {
panic!("only IPv4 remote address is supported");
};
info!("Remote address is: {}", remote_addr);
let tun_local: Ipv4Addr = matches
.value_of("tun_local")
.unwrap()

View File

@@ -4,7 +4,7 @@ use clap::{crate_version, App, Arg};
use fake_tcp::packet::MAX_PACKET_LEN;
use fake_tcp::Stack;
use log::{error, info};
use std::net::{Ipv4Addr, SocketAddr};
use std::net::Ipv4Addr;
use tokio::net::UdpSocket;
use tokio::time::{self, Duration};
use tokio_tun::TunBuilder;
@@ -31,8 +31,8 @@ async fn main() {
.short("r")
.long("remote")
.required(true)
.value_name("IP:PORT")
.help("Sets the address and port where Phantun Server forwards UDP packets to, IPv6 address need to be specified as: \"[IPv6]:PORT\"")
.value_name("IP or HOST NAME:PORT")
.help("Sets the address or host name and port where Phantun Server forwards UDP packets to, IPv6 address need to be specified as: \"[IPv6]:PORT\"")
.takes_value(true),
)
.arg(
@@ -71,11 +71,14 @@ async fn main() {
.unwrap()
.parse()
.expect("bad local port");
let remote_addr: SocketAddr = matches
.value_of("remote")
.unwrap()
.parse()
.expect("bad remote address");
let remote_addr = tokio::net::lookup_host(matches.value_of("remote").unwrap())
.await
.expect("bad remote address or host")
.next()
.expect("unable to resolve remote host name");
info!("Remote address is: {}", remote_addr);
let tun_local: Ipv4Addr = matches
.value_of("tun_local")
.unwrap()