command ack for ExitNode setting
This commit is contained in:
parent
240b60636f
commit
74a549dea9
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2141,7 +2141,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "punchnet"
|
name = "punchnet"
|
||||||
version = "1.0.3"
|
version = "1.0.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "punchnet"
|
name = "punchnet"
|
||||||
version = "1.0.3"
|
version = "1.0.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -107,21 +107,53 @@ message SDLPolicyResponse {
|
|||||||
|
|
||||||
// 事件定义
|
// 事件定义
|
||||||
|
|
||||||
message SDLNatChangedEvent {
|
message SDLEvent {
|
||||||
bytes mac = 1;
|
// nat映射变化
|
||||||
uint32 ip = 2;
|
message NatChanged {
|
||||||
|
bytes mac = 1;
|
||||||
|
uint32 ip = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送register消息
|
||||||
|
message SendRegister {
|
||||||
|
bytes dst_mac = 1;
|
||||||
|
uint32 nat_ip = 2;
|
||||||
|
uint32 nat_port = 3;
|
||||||
|
uint32 nat_type = 4;
|
||||||
|
optional SDLV6Info v6_info = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 网络关闭
|
||||||
|
message NetworkShutdown {
|
||||||
|
string message = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
oneof event {
|
||||||
|
NatChanged nat_changed = 1;
|
||||||
|
SendRegister send_register = 2;
|
||||||
|
NetworkShutdown shutdown = 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message SDLSendRegisterEvent {
|
// Command指令
|
||||||
bytes dst_mac = 1;
|
message SDLCommand {
|
||||||
uint32 nat_ip = 2;
|
uint32 pkt_id = 1;
|
||||||
uint32 nat_port = 3;
|
// 出口节点控制
|
||||||
uint32 nat_type = 4;
|
message ExitNodeControl {
|
||||||
optional SDLV6Info v6_info = 5;
|
int32 action = 1; // 必选:操作类型
|
||||||
|
string remark = 2; // 可选:备注(方便日志/调试)
|
||||||
|
}
|
||||||
|
|
||||||
|
oneof command {
|
||||||
|
ExitNodeControl exit_node = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message SDLNetworkShutdownEvent {
|
message SDLCommandAck {
|
||||||
string message = 1;
|
uint32 pkt_id = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
string message = 3;
|
||||||
|
bytes data = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDP通讯消息
|
// UDP通讯消息
|
||||||
|
|||||||
@ -25,4 +25,7 @@ pub const DNS_IP: u32 = (100<<24) + (100<<16) + (100<<8) + 100;
|
|||||||
mod tun;
|
mod tun;
|
||||||
pub use tun::{get_install_channel, restore_dns, arp_reply_arrived};
|
pub use tun::{get_install_channel, restore_dns, arp_reply_arrived};
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub use tun::{set_allow_routing, set_disallow_routing};
|
||||||
|
|
||||||
mod device;
|
mod device;
|
||||||
|
|||||||
@ -739,7 +739,7 @@ pub struct NodeConfig {
|
|||||||
// node name
|
// node name
|
||||||
pub name: String,
|
pub name: String,
|
||||||
// 允许路由
|
// 允许路由
|
||||||
pub allow_routing: bool,
|
pub allow_routing: AtomicBool,
|
||||||
|
|
||||||
// 丢弃多播,广播消息
|
// 丢弃多播,广播消息
|
||||||
pub _drop_multicast: bool,
|
pub _drop_multicast: bool,
|
||||||
|
|||||||
@ -10,7 +10,6 @@ use tracing::{debug, error};
|
|||||||
|
|
||||||
use crate::{RouteTableTrie, network::tun::{add_route, del_route}, pb::{SdlArpResponse, SdlStunReply}};
|
use crate::{RouteTableTrie, network::tun::{add_route, del_route}, pb::{SdlArpResponse, SdlStunReply}};
|
||||||
|
|
||||||
|
|
||||||
pub struct RouteTable2 {
|
pub struct RouteTable2 {
|
||||||
pub cache_table: DashMap<(Ipv4Net, Ipv4Addr), AtomicBool, RandomState>,
|
pub cache_table: DashMap<(Ipv4Net, Ipv4Addr), AtomicBool, RandomState>,
|
||||||
pub route_table: RouteTableTrie,
|
pub route_table: RouteTableTrie,
|
||||||
|
|||||||
@ -170,7 +170,7 @@ impl Iface {
|
|||||||
|
|
||||||
node.route_table.apply_system();
|
node.route_table.apply_system();
|
||||||
|
|
||||||
if node.config.allow_routing {
|
if node.config.allow_routing.load(Ordering::Relaxed) {
|
||||||
set_allow_routing();
|
set_allow_routing();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -933,8 +933,23 @@ pub fn add_route(net: &Ipv4Net, gw: &Ipv4Addr) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_disallow_routing() {
|
||||||
|
let _ = Command::new("sysctl")
|
||||||
|
.arg("-w")
|
||||||
|
.arg("net.ipv4.ip_forward=0")
|
||||||
|
.output();
|
||||||
|
|
||||||
fn set_allow_routing() {
|
let _ = Command::new("iptables")
|
||||||
|
.arg("-t")
|
||||||
|
.arg("nat")
|
||||||
|
.arg("-D")
|
||||||
|
.arg("POSTROUTING")
|
||||||
|
.arg("-j")
|
||||||
|
.arg("MASQUERADE")
|
||||||
|
.output();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_allow_routing() {
|
||||||
let _ = Command::new("sysctl")
|
let _ = Command::new("sysctl")
|
||||||
.arg("-w")
|
.arg("-w")
|
||||||
.arg("net.ipv4.ip_forward=1")
|
.arg("net.ipv4.ip_forward=1")
|
||||||
|
|||||||
@ -151,31 +151,94 @@ pub struct SdlPolicyResponse {
|
|||||||
}
|
}
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
pub struct SdlNatChangedEvent {
|
pub struct SdlEvent {
|
||||||
#[prost(bytes = "vec", tag = "1")]
|
#[prost(oneof = "sdl_event::Event", tags = "1, 2, 3")]
|
||||||
pub mac: ::prost::alloc::vec::Vec<u8>,
|
pub event: ::core::option::Option<sdl_event::Event>,
|
||||||
#[prost(uint32, tag = "2")]
|
}
|
||||||
pub ip: u32,
|
/// Nested message and enum types in `SDLEvent`.
|
||||||
|
pub mod sdl_event {
|
||||||
|
/// nat映射变化
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct NatChanged {
|
||||||
|
#[prost(bytes = "vec", tag = "1")]
|
||||||
|
pub mac: ::prost::alloc::vec::Vec<u8>,
|
||||||
|
#[prost(uint32, tag = "2")]
|
||||||
|
pub ip: u32,
|
||||||
|
}
|
||||||
|
/// 发送register消息
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SendRegister {
|
||||||
|
#[prost(bytes = "vec", tag = "1")]
|
||||||
|
pub dst_mac: ::prost::alloc::vec::Vec<u8>,
|
||||||
|
#[prost(uint32, tag = "2")]
|
||||||
|
pub nat_ip: u32,
|
||||||
|
#[prost(uint32, tag = "3")]
|
||||||
|
pub nat_port: u32,
|
||||||
|
#[prost(uint32, tag = "4")]
|
||||||
|
pub nat_type: u32,
|
||||||
|
#[prost(message, optional, tag = "5")]
|
||||||
|
pub v6_info: ::core::option::Option<super::Sdlv6Info>,
|
||||||
|
}
|
||||||
|
/// 网络关闭
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct NetworkShutdown {
|
||||||
|
#[prost(string, tag = "1")]
|
||||||
|
pub message: ::prost::alloc::string::String,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Oneof)]
|
||||||
|
pub enum Event {
|
||||||
|
#[prost(message, tag = "1")]
|
||||||
|
NatChanged(NatChanged),
|
||||||
|
#[prost(message, tag = "2")]
|
||||||
|
SendRegister(SendRegister),
|
||||||
|
#[prost(message, tag = "3")]
|
||||||
|
Shutdown(NetworkShutdown),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Command指令
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlCommand {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub pkt_id: u32,
|
||||||
|
#[prost(oneof = "sdl_command::Command", tags = "2")]
|
||||||
|
pub command: ::core::option::Option<sdl_command::Command>,
|
||||||
|
}
|
||||||
|
/// Nested message and enum types in `SDLCommand`.
|
||||||
|
pub mod sdl_command {
|
||||||
|
/// 出口节点控制
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct ExitNodeControl {
|
||||||
|
/// 必选:操作类型
|
||||||
|
#[prost(int32, tag = "1")]
|
||||||
|
pub action: i32,
|
||||||
|
/// 可选:备注(方便日志/调试)
|
||||||
|
#[prost(string, tag = "2")]
|
||||||
|
pub remark: ::prost::alloc::string::String,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Oneof)]
|
||||||
|
pub enum Command {
|
||||||
|
#[prost(message, tag = "2")]
|
||||||
|
ExitNode(ExitNodeControl),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
pub struct SdlSendRegisterEvent {
|
pub struct SdlCommandAck {
|
||||||
#[prost(bytes = "vec", tag = "1")]
|
#[prost(uint32, tag = "1")]
|
||||||
pub dst_mac: ::prost::alloc::vec::Vec<u8>,
|
pub pkt_id: u32,
|
||||||
#[prost(uint32, tag = "2")]
|
#[prost(int32, tag = "2")]
|
||||||
pub nat_ip: u32,
|
pub code: i32,
|
||||||
#[prost(uint32, tag = "3")]
|
#[prost(string, tag = "3")]
|
||||||
pub nat_port: u32,
|
|
||||||
#[prost(uint32, tag = "4")]
|
|
||||||
pub nat_type: u32,
|
|
||||||
#[prost(message, optional, tag = "5")]
|
|
||||||
pub v6_info: ::core::option::Option<Sdlv6Info>,
|
|
||||||
}
|
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
|
||||||
pub struct SdlNetworkShutdownEvent {
|
|
||||||
#[prost(string, tag = "1")]
|
|
||||||
pub message: ::prost::alloc::string::String,
|
pub message: ::prost::alloc::string::String,
|
||||||
|
#[prost(bytes = "vec", tag = "4")]
|
||||||
|
pub data: ::prost::alloc::vec::Vec<u8>,
|
||||||
}
|
}
|
||||||
/// client和stun之间的心跳包,客户端需要和super的udp之间的存活逻辑
|
/// client和stun之间的心跳包,客户端需要和super的udp之间的存活逻辑
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
|||||||
@ -17,10 +17,6 @@ static RULE_CACHE: OnceLock<DashMap<IdentityID, (u64, HashMap<Port, HashSet<Prot
|
|||||||
|
|
||||||
// static RULE_CACHE: OnceLock<DashMap<IdentityID, HashMap<Port, HashMap<Proto, AtomicU64>>>> = OnceLock::new();
|
// static RULE_CACHE: OnceLock<DashMap<IdentityID, HashMap<Port, HashMap<Proto, AtomicU64>>>> = OnceLock::new();
|
||||||
|
|
||||||
pub fn init_identity_cache() {
|
|
||||||
RULE_CACHE.set(DashMap::new()).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_identity_cache(identity: IdentityID, infos: Vec<RuleInfo>) {
|
pub fn set_identity_cache(identity: IdentityID, infos: Vec<RuleInfo>) {
|
||||||
debug!("setting identity cache for identity={}, infos: {:?}", identity, infos);
|
debug!("setting identity cache for identity={}, infos: {:?}", identity, infos);
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use std::{net::IpAddr, sync::{Arc, OnceLock, atomic::{AtomicBool, AtomicU64, Ordering}}, time::Duration};
|
use std::{net::IpAddr, sync::{Arc, OnceLock, atomic::{AtomicBool, AtomicU64, Ordering}}, time::Duration};
|
||||||
|
|
||||||
use futures_util::pin_mut;
|
use futures_util::pin_mut;
|
||||||
|
use libc::PR_SET_THP_DISABLE;
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
use quinn::SendStream;
|
use quinn::SendStream;
|
||||||
use sdlan_sn_rs::{config::AF_INET, peer::{SdlanSock, V6Info}, utils::{Result, SDLanError, get_current_timestamp, ip_to_string, rsa_decrypt}};
|
use sdlan_sn_rs::{config::AF_INET, peer::{SdlanSock, V6Info}, utils::{Result, SDLanError, get_current_timestamp, ip_to_string, rsa_decrypt}};
|
||||||
@ -9,7 +10,9 @@ use tokio::{sync::mpsc::{Receiver, Sender, channel}, time::sleep};
|
|||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
use tracing::{debug, error, warn};
|
use tracing::{debug, error, warn};
|
||||||
|
|
||||||
use crate::{AesEncryptor, Chacha20Encryptor, ConnectionInfo, ConnectionState, MyEncryptor, RuleFromServer, config::{NULL_MAC, TCP_PING_TIME}, get_edge, network::{ARP_REPLY, ArpHdr, EthHdr, Node, RegisterSuperFeedback, StartStopInfo, arp_reply_arrived, check_peer_registration_needed, handle_packet_peer_info}, pb::{SdlArpResponse, SdlPolicyResponse, SdlRegisterSuper, SdlRegisterSuperAck, SdlRegisterSuperNak, SdlSendRegisterEvent, encode_to_tcp_message}, tcp::{EventType, NakMsgCode, NatType, PacketType, SdlanTcp, read_a_packet, send_stun_request}};
|
#[cfg(target_os = "linux")]
|
||||||
|
use crate::network::{set_allow_routing, set_disallow_routing};
|
||||||
|
use crate::{AesEncryptor, Chacha20Encryptor, ConnectionInfo, ConnectionState, MyEncryptor, RuleFromServer, config::{NULL_MAC, TCP_PING_TIME}, get_edge, network::{ARP_REPLY, ArpHdr, EthHdr, Node, RegisterSuperFeedback, StartStopInfo, arp_reply_arrived, check_peer_registration_needed, handle_packet_peer_info}, pb::{SdlArpResponse, SdlCommand, SdlCommandAck, SdlEvent, SdlPolicyResponse, SdlRegisterSuper, SdlRegisterSuperAck, SdlRegisterSuperNak, encode_to_tcp_message, sdl_command, sdl_event::{self, Event, SendRegister}}, tcp::{EventType, NakMsgCode, NatType, PacketType, SdlanTcp, read_a_packet, send_stun_request}};
|
||||||
|
|
||||||
static GLOBAL_QUIC_HANDLE: OnceLock<ReadWriterHandle> = OnceLock::new();
|
static GLOBAL_QUIC_HANDLE: OnceLock<ReadWriterHandle> = OnceLock::new();
|
||||||
|
|
||||||
@ -316,18 +319,14 @@ async fn handle_tcp_message(msg: SdlanTcp) {
|
|||||||
error!("malformed COMMAND received");
|
error!("malformed COMMAND received");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
handle_tcp_command(edge, msg.current_packet[0], &msg.current_packet[1..]).await;
|
handle_tcp_command(edge, &msg.current_packet[..]).await;
|
||||||
}
|
}
|
||||||
PacketType::Event => {
|
PacketType::Event => {
|
||||||
if msg.current_packet.len() < 1 {
|
if msg.current_packet.len() < 1 {
|
||||||
error!("malformed EVENT received");
|
error!("malformed EVENT received");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let Ok(event) = msg.current_packet[0].try_into() else {
|
handle_tcp_event(edge, &msg.current_packet[..]).await;
|
||||||
error!("failed to parse event type");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
handle_tcp_event(edge, event, &msg.current_packet[1..]).await;
|
|
||||||
}
|
}
|
||||||
PacketType::PeerInfo => {
|
PacketType::PeerInfo => {
|
||||||
let _ = handle_packet_peer_info(edge, &msg.current_packet[..]).await;
|
let _ = handle_packet_peer_info(edge, &msg.current_packet[..]).await;
|
||||||
@ -344,15 +343,69 @@ async fn handle_tcp_message(msg: SdlanTcp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn handle_tcp_command(_edge: &Node, _cmdtype: u8, _cmdprotobuf: &[u8]) {}
|
async fn handle_tcp_command(edge: &Node, cmdprotobuf: &[u8]) {
|
||||||
|
let Ok(cmd) = SdlCommand::decode(cmdprotobuf) else {
|
||||||
|
error!("failed to decode SdlCommand");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
async fn handle_tcp_event(edge: &'static Node, eventtype: EventType, eventprotobuf: &[u8]) {
|
let pkt_id = cmd.pkt_id;
|
||||||
match eventtype {
|
let Some(command) = cmd.command else {
|
||||||
EventType::SendRegister => {
|
error!("command type is none");
|
||||||
let Ok(reg) = SdlSendRegisterEvent::decode(eventprotobuf) else {
|
return;
|
||||||
error!("failed to decode SendRegister Event");
|
};
|
||||||
return;
|
|
||||||
|
match command {
|
||||||
|
sdl_command::Command::ExitNode(node) => {
|
||||||
|
debug!("got exit node command: {:?}", node);
|
||||||
|
// println!("got exit node command: {:?}", node);
|
||||||
|
// std::process::exit(0);
|
||||||
|
if node.action == 0 {
|
||||||
|
// stop
|
||||||
|
let origin = edge.config.allow_routing.fetch_and(false, Ordering::Relaxed);
|
||||||
|
if origin {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
set_disallow_routing();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// start
|
||||||
|
let origin = edge.config.allow_routing.fetch_or(true, Ordering::Relaxed);
|
||||||
|
if !origin {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
set_allow_routing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ack = SdlCommandAck{
|
||||||
|
pkt_id,
|
||||||
|
code: 0,
|
||||||
|
message: "ok".to_owned(),
|
||||||
|
data: vec![],
|
||||||
};
|
};
|
||||||
|
let msg = encode_to_tcp_message(Some(ack), PacketType::CommandACK as u8).unwrap();
|
||||||
|
|
||||||
|
let stream = get_quic_write_conn();
|
||||||
|
if let Err(e) = stream.send(msg).await {
|
||||||
|
error!("failed to write command ack to quic: {}", e.as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_tcp_event(edge: &'static Node, eventprotobuf: &[u8]) {
|
||||||
|
let Ok(sdl_event) = SdlEvent::decode(eventprotobuf) else {
|
||||||
|
error!("failed to decode SdlEvent");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(event) = sdl_event.event else {
|
||||||
|
error!("event type is none");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
match event {
|
||||||
|
sdl_event::Event::SendRegister(reg) => {
|
||||||
let v4 = reg.nat_ip.to_be_bytes();
|
let v4 = reg.nat_ip.to_be_bytes();
|
||||||
let mut v6_sock = None;
|
let mut v6_sock = None;
|
||||||
if let Some(v6_info) = reg.v6_info {
|
if let Some(v6_info) = reg.v6_info {
|
||||||
@ -391,10 +444,12 @@ async fn handle_tcp_event(edge: &'static Node, eventtype: EventType, eventprotob
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
other => {
|
other => {
|
||||||
debug!("unhandled event {:?}", other);
|
debug!("unhandled event {:?}", other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user