-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
719 additions
and
229 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
--- | ||
port: 8888 | ||
socks-port: 8889 | ||
mixed-port: 8899 | ||
|
||
|
||
dns: | ||
enable: true | ||
listen: 127.0.0.1:53533 | ||
# ipv6: false # when the false, response to AAAA questions will be empty | ||
|
||
# These nameservers are used to resolve the DNS nameserver hostnames below. | ||
# Specify IP addresses only | ||
default-nameserver: | ||
- 114.114.114.114 | ||
- 8.8.8.8 | ||
enhanced-mode: fake-ip # or fake-ip | ||
fake-ip-range: 198.18.0.1/16 # Fake IP addresses pool CIDR | ||
# use-hosts: true # lookup hosts and return IP record | ||
|
||
# Hostnames in this list will not be resolved with fake IPs | ||
# i.e. questions to these domain names will always be answered with their | ||
# real IP addresses | ||
# fake-ip-filter: | ||
# - '*.lan' | ||
# - localhost.ptlogin2.qq.com | ||
|
||
# Supports UDP, TCP, DoT, DoH. You can specify the port to connect to. | ||
# All DNS questions are sent directly to the nameserver, without proxies | ||
# involved. Clash answers the DNS question with the first result gathered. | ||
nameserver: | ||
- 114.114.114.114 # default value | ||
- 8.8.8.8 # default value | ||
- tls://dns.google:853 # DNS over TLS | ||
- https://1.1.1.1/dns-query # DNS over HTTPS | ||
- dhcp://en0 # dns from dhcp | ||
|
||
allow-lan: true | ||
mode: rule | ||
log-level: debug | ||
external-controller: 127.0.0.1:6170 | ||
experimental: | ||
ignore-resolve-fail: true | ||
|
||
proxies: | ||
- name: "wg" | ||
type: wireguard | ||
server: 10.0.0.17 | ||
port: 51820 | ||
private-key: 2AS8PSccSenWrws5ExglmpwjVBub9Oy9X3zOlk6heHU= | ||
ip: 172.16.0.2 | ||
public-key: MAZPwQBniuXmQf5w8BwM3owlO7Kw07rzyZUXxOvsF3w= | ||
allowed-ips: ['0.0.0.0/0'] | ||
udp: true | ||
|
||
|
||
rules: | ||
- MATCH, wg | ||
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod shadowsocks; | ||
pub mod trojan; | ||
pub mod vmess; | ||
pub mod wireguard; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
use crate::{ | ||
config::internal::proxy::OutboundWireguard, | ||
proxy::{ | ||
wg::{Handler, Opts}, | ||
AnyOutboundHandler, | ||
}, | ||
Error, | ||
}; | ||
|
||
impl TryFrom<OutboundWireguard> for AnyOutboundHandler { | ||
type Error = crate::Error; | ||
|
||
fn try_from(value: OutboundWireguard) -> Result<Self, Self::Error> { | ||
(&value).try_into() | ||
} | ||
} | ||
|
||
impl TryFrom<&OutboundWireguard> for AnyOutboundHandler { | ||
type Error = crate::Error; | ||
|
||
fn try_from(s: &OutboundWireguard) -> Result<Self, Self::Error> { | ||
let h = Handler::new(Opts { | ||
name: s.name.to_owned(), | ||
common_opts: Default::default(), | ||
server: s.server.to_owned(), | ||
port: s.port, | ||
ip: s | ||
.ip | ||
.parse() | ||
.map_err(|x| Error::InvalidConfig(format!("invalid ip address: {}", x)))?, | ||
ipv6: s | ||
.ipv6 | ||
.as_ref() | ||
.map(|x| { | ||
x.parse() | ||
.map_err(|x| Error::InvalidConfig(format!("invalid ipv6 address: {}", x))) | ||
}) | ||
.transpose()?, | ||
private_key: s.private_key.to_owned(), | ||
public_key: s.public_key.to_owned(), | ||
preshared_key: s.preshared_key.as_ref().map(|x| x.to_owned()), | ||
remote_dns_resolve: false, | ||
dns: None, | ||
mtu: s.mtu, | ||
udp: s.udp.unwrap_or_default(), | ||
}); | ||
Ok(h) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,114 @@ | ||
use std::{ | ||
collections::VecDeque, | ||
sync::{Arc, Mutex}, | ||
}; | ||
use bytes::{Bytes, BytesMut}; | ||
use smoltcp::phy::Device; | ||
use tokio::sync::mpsc::{Receiver, Sender}; | ||
use tracing::error; | ||
|
||
use bytes::Bytes; | ||
|
||
use super::events::BusSender; | ||
use super::{events::PortProtocol, ports::PortPool}; | ||
|
||
pub struct VirtualIpDevice { | ||
mtu: usize, | ||
bus_sender: BusSender, | ||
queue: Arc<Mutex<VecDeque<Bytes>>>, | ||
|
||
tcp_port_pool: PortPool, | ||
|
||
packet_sender: Sender<Bytes>, | ||
packet_receiver: Receiver<(PortProtocol, Bytes)>, | ||
} | ||
|
||
impl VirtualIpDevice { | ||
pub fn new( | ||
packet_sender: Sender<Bytes>, | ||
packet_receiver: Receiver<(PortProtocol, Bytes)>, | ||
mtu: usize, | ||
) -> Self { | ||
Self { | ||
mtu, | ||
tcp_port_pool: PortPool::new(), | ||
packet_sender, | ||
packet_receiver, | ||
} | ||
} | ||
|
||
pub async fn get_ephemeral_tcp_port(&self) -> u16 { | ||
self.tcp_port_pool.next().await.unwrap() | ||
} | ||
pub async fn release_ephemeral_tcp_port(&self, port: u16) { | ||
self.tcp_port_pool.release(port).await; | ||
} | ||
} | ||
|
||
impl Device for VirtualIpDevice { | ||
type RxToken<'a> = RxToken; | ||
type TxToken<'a> = TxToken; | ||
|
||
fn receive( | ||
&mut self, | ||
timestamp: smoltcp::time::Instant, | ||
) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { | ||
let next = self.packet_receiver.try_recv().ok(); | ||
|
||
match next { | ||
Some((proto, data)) => { | ||
let rx_token = RxToken { | ||
buffer: { | ||
let mut buffer = BytesMut::new(); | ||
buffer.extend_from_slice(&data); | ||
buffer | ||
}, | ||
}; | ||
let tx_token = TxToken { | ||
sender: self.packet_sender.clone(), | ||
}; | ||
Some((rx_token, tx_token)) | ||
} | ||
None => None, | ||
} | ||
} | ||
|
||
fn transmit(&mut self, timestamp: smoltcp::time::Instant) -> Option<Self::TxToken<'_>> { | ||
Some(TxToken { | ||
sender: self.packet_sender.clone(), | ||
}) | ||
} | ||
|
||
fn capabilities(&self) -> smoltcp::phy::DeviceCapabilities { | ||
let mut caps = smoltcp::phy::DeviceCapabilities::default(); | ||
caps.medium = smoltcp::phy::Medium::Ip; | ||
caps.max_transmission_unit = self.mtu; | ||
caps | ||
} | ||
} | ||
|
||
pub struct RxToken { | ||
buffer: BytesMut, | ||
} | ||
|
||
impl smoltcp::phy::RxToken for RxToken { | ||
fn consume<R, F>(mut self, f: F) -> R | ||
where | ||
F: FnOnce(&mut [u8]) -> R, | ||
{ | ||
f(&mut self.buffer) | ||
} | ||
} | ||
|
||
pub struct TxToken { | ||
sender: Sender<Bytes>, | ||
} | ||
|
||
impl smoltcp::phy::TxToken for TxToken { | ||
fn consume<R, F>(self, len: usize, f: F) -> R | ||
where | ||
F: FnOnce(&mut [u8]) -> R, | ||
{ | ||
let mut buffer = Vec::new(); | ||
buffer.resize(len, 0); | ||
let result = f(&mut buffer); | ||
match self.sender.try_send(buffer.into()) { | ||
Ok(_) => {} | ||
Err(err) => { | ||
error!("failed to send packet: {}", err); | ||
} | ||
} | ||
result | ||
} | ||
} |
Oops, something went wrong.