mirror of
https://github.com/EasyTier/EasyTier.git
synced 2024-11-16 11:42:27 +08:00
support exit node (#121)
support exit node, proxy all traffic via one of node NOTE: this patch has not implemented automatically route management.
This commit is contained in:
parent
6efbb5cb3d
commit
f64f58e2ae
|
@ -1,5 +1,5 @@
|
|||
use std::{
|
||||
net::SocketAddr,
|
||||
net::{Ipv4Addr, SocketAddr},
|
||||
path::PathBuf,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
@ -58,6 +58,9 @@ pub trait ConfigLoader: Send + Sync {
|
|||
fn get_flags(&self) -> Flags;
|
||||
fn set_flags(&self, flags: Flags);
|
||||
|
||||
fn get_exit_nodes(&self) -> Vec<Ipv4Addr>;
|
||||
fn set_exit_nodes(&self, nodes: Vec<Ipv4Addr>);
|
||||
|
||||
fn dump(&self) -> String;
|
||||
}
|
||||
|
||||
|
@ -155,6 +158,8 @@ pub struct Flags {
|
|||
pub mtu: u16,
|
||||
#[derivative(Default(value = "true"))]
|
||||
pub latency_first: bool,
|
||||
#[derivative(Default(value = "false"))]
|
||||
pub enable_exit_node: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
||||
|
@ -167,6 +172,7 @@ struct Config {
|
|||
dhcp: Option<bool>,
|
||||
network_identity: Option<NetworkIdentity>,
|
||||
listeners: Option<Vec<url::Url>>,
|
||||
exit_nodes: Option<Vec<Ipv4Addr>>,
|
||||
|
||||
peer: Option<Vec<PeerConfig>>,
|
||||
proxy_network: Option<Vec<NetworkConfig>>,
|
||||
|
@ -459,6 +465,19 @@ impl ConfigLoader for TomlConfigLoader {
|
|||
self.config.lock().unwrap().flags = Some(flags);
|
||||
}
|
||||
|
||||
fn get_exit_nodes(&self) -> Vec<Ipv4Addr> {
|
||||
self.config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.exit_nodes
|
||||
.clone()
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn set_exit_nodes(&self, nodes: Vec<Ipv4Addr>) {
|
||||
self.config.lock().unwrap().exit_nodes = Some(nodes);
|
||||
}
|
||||
|
||||
fn dump(&self) -> String {
|
||||
toml::to_string_pretty(&*self.config.lock().unwrap()).unwrap()
|
||||
}
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use std::{backtrace, io::Write as _, net::SocketAddr, path::PathBuf};
|
||||
use std::{
|
||||
backtrace,
|
||||
io::Write as _,
|
||||
net::{Ipv4Addr, SocketAddr},
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use clap::Parser;
|
||||
|
@ -179,6 +184,20 @@ and the vpn client is in network of 10.14.14.0/24"
|
|||
default_value = "false"
|
||||
)]
|
||||
latency_first: bool,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "exit nodes to forward all traffic to, a virtual ipv4 address, priority is determined by the order of the list",
|
||||
num_args = 0..
|
||||
)]
|
||||
exit_nodes: Vec<Ipv4Addr>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "allow this node to be an exit node, default is false",
|
||||
default_value = "false"
|
||||
)]
|
||||
enable_exit_node: bool,
|
||||
}
|
||||
|
||||
impl Cli {
|
||||
|
@ -394,8 +413,11 @@ impl From<Cli> for TomlConfigLoader {
|
|||
if let Some(mtu) = cli.mtu {
|
||||
f.mtu = mtu;
|
||||
}
|
||||
f.enable_exit_node = cli.enable_exit_node;
|
||||
cfg.set_flags(f);
|
||||
|
||||
cfg.set_exit_nodes(cli.exit_nodes.clone());
|
||||
|
||||
cfg
|
||||
}
|
||||
}
|
||||
|
|
|
@ -248,6 +248,7 @@ impl IcmpProxy {
|
|||
async fn try_handle_peer_packet(&self, packet: &ZCPacket) -> Option<()> {
|
||||
let _ = self.global_ctx.get_ipv4()?;
|
||||
let hdr = packet.peer_manager_header().unwrap();
|
||||
let is_exit_node = hdr.is_exit_node();
|
||||
|
||||
if hdr.packet_type != PacketType::Data as u8 {
|
||||
return None;
|
||||
|
@ -260,7 +261,7 @@ impl IcmpProxy {
|
|||
return None;
|
||||
}
|
||||
|
||||
if !self.cidr_set.contains_v4(ipv4.get_destination()) {
|
||||
if !self.cidr_set.contains_v4(ipv4.get_destination()) && !is_exit_node {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
@ -358,6 +358,7 @@ impl TcpProxy {
|
|||
async fn try_handle_peer_packet(&self, packet: &mut ZCPacket) -> Option<()> {
|
||||
let ipv4_addr = self.global_ctx.get_ipv4()?;
|
||||
let hdr = packet.peer_manager_header().unwrap();
|
||||
let is_exit_node = hdr.is_exit_node();
|
||||
|
||||
if hdr.packet_type != PacketType::Data as u8 {
|
||||
return None;
|
||||
|
@ -370,7 +371,7 @@ impl TcpProxy {
|
|||
return None;
|
||||
}
|
||||
|
||||
if !self.cidr_set.contains_v4(ipv4.get_destination()) {
|
||||
if !self.cidr_set.contains_v4(ipv4.get_destination()) && !is_exit_node {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
@ -233,6 +233,7 @@ impl UdpProxy {
|
|||
|
||||
let _ = self.global_ctx.get_ipv4()?;
|
||||
let hdr = packet.peer_manager_header().unwrap();
|
||||
let is_exit_node = hdr.is_exit_node();
|
||||
if hdr.packet_type != PacketType::Data as u8 {
|
||||
return None;
|
||||
};
|
||||
|
@ -242,7 +243,7 @@ impl UdpProxy {
|
|||
return None;
|
||||
}
|
||||
|
||||
if !self.cidr_set.contains_v4(ipv4.get_destination()) {
|
||||
if !self.cidr_set.contains_v4(ipv4.get_destination()) && !is_exit_node {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,9 @@ impl IpProxy {
|
|||
}
|
||||
|
||||
async fn start(&self) -> Result<(), Error> {
|
||||
if self.global_ctx.get_proxy_cidrs().is_empty() || self.started.load(Ordering::Relaxed) {
|
||||
if (self.global_ctx.get_proxy_cidrs().is_empty() || self.started.load(Ordering::Relaxed))
|
||||
&& !self.global_ctx.config.get_flags().enable_exit_node
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
|
|
@ -155,6 +155,8 @@ pub struct PeerManager {
|
|||
foreign_network_client: Arc<ForeignNetworkClient>,
|
||||
|
||||
encryptor: Arc<Box<dyn Encryptor>>,
|
||||
|
||||
exit_nodes: Vec<Ipv4Addr>,
|
||||
}
|
||||
|
||||
impl Debug for PeerManager {
|
||||
|
@ -238,6 +240,8 @@ impl PeerManager {
|
|||
my_peer_id,
|
||||
));
|
||||
|
||||
let exit_nodes = global_ctx.config.get_exit_nodes();
|
||||
|
||||
PeerManager {
|
||||
my_peer_id,
|
||||
|
||||
|
@ -262,6 +266,7 @@ impl PeerManager {
|
|||
foreign_network_client,
|
||||
|
||||
encryptor,
|
||||
exit_nodes,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -573,6 +578,7 @@ impl PeerManager {
|
|||
ipv4_addr
|
||||
);
|
||||
|
||||
let mut is_exit_node = false;
|
||||
let mut dst_peers = vec![];
|
||||
// NOTE: currently we only support ipv4 and cidr is 24
|
||||
if ipv4_addr.is_broadcast() || ipv4_addr.is_multicast() || ipv4_addr.octets()[3] == 255 {
|
||||
|
@ -585,6 +591,14 @@ impl PeerManager {
|
|||
);
|
||||
} else if let Some(peer_id) = self.peers.get_peer_id_by_ipv4(&ipv4_addr).await {
|
||||
dst_peers.push(peer_id);
|
||||
} else {
|
||||
for exit_node in &self.exit_nodes {
|
||||
if let Some(peer_id) = self.peers.get_peer_id_by_ipv4(exit_node).await {
|
||||
dst_peers.push(peer_id);
|
||||
is_exit_node = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if dst_peers.is_empty() {
|
||||
|
@ -605,7 +619,8 @@ impl PeerManager {
|
|||
let is_latency_first = self.global_ctx.get_flags().latency_first;
|
||||
msg.mut_peer_manager_header()
|
||||
.unwrap()
|
||||
.set_latency_first(is_latency_first);
|
||||
.set_latency_first(is_latency_first)
|
||||
.set_exit_node(is_exit_node);
|
||||
let next_hop_policy = Self::get_next_hop_policy(is_latency_first);
|
||||
|
||||
let mut errs: Vec<Error> = vec![];
|
||||
|
|
|
@ -60,6 +60,7 @@ bitflags::bitflags! {
|
|||
struct PeerManagerHeaderFlags: u8 {
|
||||
const ENCRYPTED = 0b0000_0001;
|
||||
const LATENCY_FIRST = 0b0000_0010;
|
||||
const EXIT_NODE = 0b0000_0100;
|
||||
|
||||
const _ = !0;
|
||||
}
|
||||
|
@ -101,7 +102,13 @@ impl PeerManagerHeader {
|
|||
.contains(PeerManagerHeaderFlags::LATENCY_FIRST)
|
||||
}
|
||||
|
||||
pub fn set_latency_first(&mut self, latency_first: bool) {
|
||||
pub fn is_exit_node(&self) -> bool {
|
||||
PeerManagerHeaderFlags::from_bits(self.flags)
|
||||
.unwrap()
|
||||
.contains(PeerManagerHeaderFlags::EXIT_NODE)
|
||||
}
|
||||
|
||||
pub fn set_latency_first(&mut self, latency_first: bool) -> &mut Self {
|
||||
let mut flags = PeerManagerHeaderFlags::from_bits(self.flags).unwrap();
|
||||
if latency_first {
|
||||
flags.insert(PeerManagerHeaderFlags::LATENCY_FIRST);
|
||||
|
@ -109,6 +116,18 @@ impl PeerManagerHeader {
|
|||
flags.remove(PeerManagerHeaderFlags::LATENCY_FIRST);
|
||||
}
|
||||
self.flags = flags.bits();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_exit_node(&mut self, exit_node: bool) -> &mut Self {
|
||||
let mut flags = PeerManagerHeaderFlags::from_bits(self.flags).unwrap();
|
||||
if exit_node {
|
||||
flags.insert(PeerManagerHeaderFlags::EXIT_NODE);
|
||||
} else {
|
||||
flags.remove(PeerManagerHeaderFlags::EXIT_NODE);
|
||||
}
|
||||
self.flags = flags.bits();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user