Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f60e243a89 | ||
|
|
42c9d74676 | ||
|
|
7a31f50c56 | ||
|
|
effac11504 | ||
|
|
4ff8b1d102 | ||
|
|
15777875c2 | ||
|
|
1dfe30bfdb | ||
|
|
067c3ee0f5 | ||
|
|
adcf157db3 | ||
|
|
e2541dc594 | ||
|
|
9e06f37eb0 | ||
|
|
06503e16c0 | ||
|
|
2b3c4822ab |
26
.github/workflows/ci.yml
vendored
26
.github/workflows/ci.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
- name: test leaf
|
||||
run: cargo test -p leaf
|
||||
|
||||
build-bin-cross:
|
||||
build-cli-cross:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
run: |
|
||||
export CFG_COMMIT_HASH=`git log --pretty=format:'%h' -n 1`
|
||||
export CFG_COMMIT_DATE=`git log --format="%ci" -n 1`
|
||||
./scripts/build_cross.sh ${{ matrix.target }}
|
||||
cross build --release --target ${{ matrix.target }}
|
||||
|
||||
- name: rename and compress artifacts
|
||||
if: ${{ matrix.target == 'x86_64-pc-windows-gnu' }}
|
||||
@@ -86,14 +86,14 @@ jobs:
|
||||
name: leaf-${{ matrix.target }}
|
||||
path: leaf-${{ matrix.target }}
|
||||
|
||||
build-bin-local:
|
||||
build-cli-macos:
|
||||
runs-on: [macos-latest]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
include:
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
runs-on: ${{ matrix.os }}
|
||||
target:
|
||||
- aarch64-apple-darwin
|
||||
- x86_64-apple-darwin
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
@@ -114,11 +114,15 @@ jobs:
|
||||
run: |
|
||||
brew install llvm protobuf
|
||||
|
||||
- name: install target
|
||||
run: |
|
||||
rustup target add ${{ matrix.target }}
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
export CFG_COMMIT_HASH=`git log --pretty=format:'%h' -n 1`
|
||||
export CFG_COMMIT_DATE=`git log --format="%ci" -n 1`
|
||||
cargo build --release --target ${{ matrix.target }} -p leaf-bin
|
||||
cargo build --release --target ${{ matrix.target }} -p leaf-cli
|
||||
|
||||
- name: rename and compress artifacts
|
||||
run: |
|
||||
@@ -130,7 +134,7 @@ jobs:
|
||||
name: leaf-${{ matrix.target }}
|
||||
path: leaf-${{ matrix.target }}
|
||||
|
||||
build-apple:
|
||||
build-lib-apple:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
@@ -163,7 +167,7 @@ jobs:
|
||||
name: leaf.xcframework.zip
|
||||
path: leaf.xcframework.zip
|
||||
|
||||
build-android:
|
||||
build-lib-android:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
|
||||
31
.github/workflows/release.yml
vendored
31
.github/workflows/release.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
build-bin-cross:
|
||||
build-cli-cross:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
run: |
|
||||
export CFG_COMMIT_HASH=`git log --pretty=format:'%h' -n 1`
|
||||
export CFG_COMMIT_DATE=`git log --format="%ci" -n 1`
|
||||
./scripts/build_cross.sh ${{ matrix.target }}
|
||||
cross build --release --target ${{ matrix.target }}
|
||||
|
||||
- name: rename and compress artifacts
|
||||
if: ${{ matrix.target == 'x86_64-pc-windows-gnu' }}
|
||||
@@ -63,14 +63,14 @@ jobs:
|
||||
name: leaf-${{ matrix.target }}
|
||||
path: leaf-${{ matrix.target }}
|
||||
|
||||
build-bin-local:
|
||||
build-cli-macos:
|
||||
runs-on: [macos-latest]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
include:
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
runs-on: ${{ matrix.os }}
|
||||
target:
|
||||
- aarch64-apple-darwin
|
||||
- x86_64-apple-darwin
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
@@ -87,11 +87,15 @@ jobs:
|
||||
run: |
|
||||
brew install llvm protobuf
|
||||
|
||||
- name: install target
|
||||
run: |
|
||||
rustup target add ${{ matrix.target }}
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
export CFG_COMMIT_HASH=`git log --pretty=format:'%h' -n 1`
|
||||
export CFG_COMMIT_DATE=`git log --format="%ci" -n 1`
|
||||
cargo build --release --target ${{ matrix.target }} -p leaf-bin
|
||||
cargo build --release --target ${{ matrix.target }} -p leaf-cli
|
||||
|
||||
- name: rename and compress artifacts
|
||||
run: |
|
||||
@@ -103,7 +107,7 @@ jobs:
|
||||
name: leaf-${{ matrix.target }}
|
||||
path: leaf-${{ matrix.target }}
|
||||
|
||||
build-apple:
|
||||
build-lib-apple:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
@@ -136,7 +140,7 @@ jobs:
|
||||
name: leaf.xcframework.zip
|
||||
path: leaf.xcframework.zip
|
||||
|
||||
build-android:
|
||||
build-lib-android:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
@@ -182,7 +186,7 @@ jobs:
|
||||
path: leaf-android-libs.zip
|
||||
|
||||
create-release:
|
||||
needs: [build-bin-cross, build-bin-local, build-apple, build-android]
|
||||
needs: [build-cli-cross, build-cli-macos, build-lib-apple, build-lib-android]
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
@@ -211,13 +215,14 @@ jobs:
|
||||
name: upload_url.txt
|
||||
path: ./upload_url.txt
|
||||
|
||||
release-bin:
|
||||
release-cli:
|
||||
needs: [create-release]
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
target:
|
||||
- x86_64-apple-darwin
|
||||
- aarch64-apple-darwin
|
||||
- x86_64-unknown-linux-musl
|
||||
- aarch64-unknown-linux-musl
|
||||
- x86_64-pc-windows-gnu
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,4 +1,4 @@
|
||||
.PHONY: local local-dev test proto-gen
|
||||
.PHONY: cli cli-dev test proto-gen
|
||||
|
||||
CFG_COMMIT_HASH := $(shell git rev-parse HEAD | cut -c 1-7)
|
||||
export CFG_COMMIT_HASH := $(CFG_COMMIT_HASH)
|
||||
|
||||
@@ -83,7 +83,7 @@ Clone & Build:
|
||||
```sh
|
||||
git clone --recursive https://github.com/eycorsican/leaf.git
|
||||
cd leaf
|
||||
cargo build -p leaf-bin
|
||||
cargo build -p leaf-cli
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leaf-cli"
|
||||
version = "0.10.11"
|
||||
version = "0.10.13"
|
||||
authors = ["eycorsican <eric.y.corsican@gmail.com>"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -9,13 +9,13 @@ name = "leaf"
|
||||
path = "src/main.rs"
|
||||
|
||||
[features]
|
||||
default = ["default-ring"]
|
||||
|
||||
default-ring = ["leaf/default-ring", "leaf/ctrlc", "auto-reload"]
|
||||
|
||||
default-openssl = ["leaf/default-openssl", "leaf/ctrlc", "auto-reload"]
|
||||
|
||||
auto-reload = ["leaf/auto-reload"]
|
||||
default = [
|
||||
"leaf/default-ring",
|
||||
"leaf/outbound-quic",
|
||||
"leaf/outbound-quic",
|
||||
"leaf/ctrlc",
|
||||
"leaf/auto-reload",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
leaf = { path = "../leaf", default-features = false, optional = true }
|
||||
|
||||
@@ -34,7 +34,6 @@ struct Args {
|
||||
config: String,
|
||||
|
||||
/// enables auto reloading when config file changes
|
||||
#[cfg(feature = "auto-reload")]
|
||||
#[argh(switch)]
|
||||
auto_reload: bool,
|
||||
|
||||
@@ -123,7 +122,6 @@ fn main() {
|
||||
if let Err(e) = leaf::util::run_with_options(
|
||||
0,
|
||||
args.config,
|
||||
#[cfg(feature = "auto-reload")]
|
||||
args.auto_reload,
|
||||
!args.single_thread,
|
||||
true,
|
||||
|
||||
@@ -14,6 +14,10 @@ default = [
|
||||
"default-ring",
|
||||
]
|
||||
|
||||
default-aws-lc= [
|
||||
"leaf/default-aws-lc",
|
||||
]
|
||||
|
||||
default-ring = [
|
||||
"leaf/default-ring",
|
||||
]
|
||||
|
||||
@@ -19,12 +19,19 @@ default-ring = [
|
||||
"all-endpoints",
|
||||
"ring-aead",
|
||||
"rustls-tls",
|
||||
# quinn supports only rustls as tls backend for now
|
||||
"inbound-quic",
|
||||
"outbound-quic",
|
||||
"rustls-tls-ring",
|
||||
"api",
|
||||
"stat",
|
||||
]
|
||||
|
||||
default-aws-lc = [
|
||||
"all-configs",
|
||||
"all-endpoints",
|
||||
"aws-lc-aead",
|
||||
"rustls-tls",
|
||||
"rustls-tls-aws-lc",
|
||||
"api",
|
||||
"stat",
|
||||
# "plugin",
|
||||
]
|
||||
|
||||
default-openssl = [
|
||||
@@ -34,6 +41,9 @@ default-openssl = [
|
||||
"openssl-tls",
|
||||
]
|
||||
|
||||
rustls-tls-aws-lc = ["tokio-rustls/aws_lc_rs"]
|
||||
rustls-tls-ring = ["tokio-rustls/ring"]
|
||||
|
||||
# Grouping all features
|
||||
all-configs = [
|
||||
"config-conf",
|
||||
@@ -74,6 +84,7 @@ all-endpoints = [
|
||||
|
||||
# Ring-related
|
||||
ring-aead = ["ring"]
|
||||
aws-lc-aead = ["aws-lc-rs"]
|
||||
rustls-tls = ["tokio-rustls", "webpki-roots", "rustls-pemfile"]
|
||||
|
||||
# Openssl-related, for platforms not supported by ring, such as mips
|
||||
@@ -99,7 +110,7 @@ outbound-static= []
|
||||
outbound-tryall = []
|
||||
outbound-chain = []
|
||||
outbound-amux= ["tokio-util"]
|
||||
outbound-quic = ["quinn", "rustls", "webpki-roots", "rustls-pemfile"]
|
||||
outbound-quic = ["quinn", "rustls", "webpki-roots-old", "rustls-pemfile-old"]
|
||||
outbound-select = ["directories"]
|
||||
outbound-vmess = ["lz_fnv", "cfb-mode", "hmac", "aes", "sha3", "digest", "uuid", "md-5", "tokio-util", "byteorder"]
|
||||
|
||||
@@ -111,7 +122,7 @@ inbound-http = ["http"]
|
||||
inbound-tun = ["tun", "netstack-lwip", "pnet_datalink"]
|
||||
inbound-ws = ["tungstenite", "tokio-tungstenite", "url", "http"]
|
||||
inbound-amux = ["tokio-util"]
|
||||
inbound-quic = ["quinn", "rustls", "webpki-roots"]
|
||||
inbound-quic = ["quinn", "rustls", "rustls-pemfile-old"]
|
||||
inbound-tls = []
|
||||
inbound-chain = []
|
||||
inbound-cat = ["tokio/io-std"]
|
||||
@@ -125,31 +136,31 @@ ctrlc = ["tokio/signal"]
|
||||
[dependencies]
|
||||
# Common
|
||||
tokio = { version = "1", features = ["sync", "io-util", "net", "time", "rt", "rt-multi-thread"] }
|
||||
protobuf = "=3.3.0"
|
||||
protobuf = "=3.4.0"
|
||||
thiserror = "1.0"
|
||||
futures = "0.3"
|
||||
async-trait = "0.1"
|
||||
bytes = "1"
|
||||
bytes = "1.6"
|
||||
lazy_static = "1.4"
|
||||
anyhow = "1.0"
|
||||
rand = "0.8"
|
||||
socket2 = "0.5"
|
||||
async-recursion = "1.0"
|
||||
async-recursion = "1.1"
|
||||
|
||||
# DNS
|
||||
trust-dns-proto = { version = "0.23", default-features = false }
|
||||
lru = "0.11"
|
||||
lru = "0.12"
|
||||
|
||||
# Logging
|
||||
tracing = "0.1"
|
||||
tracing-appender = "0.2"
|
||||
tracing-subscriber = "0.3"
|
||||
chrono = "0.4"
|
||||
colored = "2.0"
|
||||
colored = "2.1"
|
||||
|
||||
# Router
|
||||
maxminddb = { version = "0.23", features = ["mmap"] }
|
||||
memmap2 = "0.8"
|
||||
maxminddb = { version = "0.24", features = ["mmap"] }
|
||||
memmap2 = "0.9"
|
||||
cidr = "0.2"
|
||||
|
||||
# outbound-select
|
||||
@@ -165,42 +176,44 @@ serde_derive = { version = "1.0", optional = true }
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
# config-conf
|
||||
regex = { version = "1", optional = true }
|
||||
regex = { version = "1.10", optional = true }
|
||||
|
||||
# Openssl
|
||||
openssl = { version = "0.10", features = ["vendored"], optional = true }
|
||||
|
||||
# Ring
|
||||
ring = { version = "0.16", optional = true }
|
||||
ring = { version = "0.17", optional = true }
|
||||
|
||||
aws-lc-rs = { version = "1.7", features = ["bindgen"], optional = true }
|
||||
|
||||
# TLS/rustls/QUIC
|
||||
tokio-rustls = { version = "0.24", features = ["dangerous_configuration"], optional = true }
|
||||
webpki-roots = { version = "0.25", optional = true }
|
||||
rustls-pemfile = { version = "1.0", optional = true }
|
||||
tokio-rustls = { version = "0.26", default-features = false, features = ["logging", "tls12"], optional = true }
|
||||
webpki-roots = { version = "0.26", optional = true }
|
||||
webpki-roots-old = { package = "webpki-roots", version = "0.25", optional = true }
|
||||
rustls-pemfile = { version = "2.1", optional = true }
|
||||
rustls-pemfile-old = { package = "rustls-pemfile", version = "1.0", optional = true }
|
||||
|
||||
# TLS/openssl
|
||||
openssl-probe = { version = "0.1", optional = true }
|
||||
tokio-openssl = { version = "0.6", optional = true }
|
||||
|
||||
# WebSocket
|
||||
tungstenite = { version = "0.20", default-features = false, optional = true }
|
||||
tokio-tungstenite = { version = "0.20", optional = true }
|
||||
tungstenite = { version = "0.21", default-features = false, optional = true }
|
||||
tokio-tungstenite = { version = "0.21", optional = true }
|
||||
|
||||
# WebSocket
|
||||
url = { version = "2.4", optional = true }
|
||||
http = { version = "0.2", optional = true }
|
||||
url = { version = "2.5", optional = true }
|
||||
http = { version = "1.1", optional = true }
|
||||
|
||||
# SOCKS outbound
|
||||
async-socks5 = { version = "0.5", optional = true }
|
||||
async-socks5 = { version = "0.6", optional = true }
|
||||
|
||||
# Shadowsocks
|
||||
hkdf = { version = "0.12", optional = true }
|
||||
md-5 = { version = "0.10", optional = true }
|
||||
sha-1 = { version = "0.10", optional = true }
|
||||
percent-encoding = { version = "2", optional = true }
|
||||
percent-encoding = { version = "2.3", optional = true }
|
||||
|
||||
# Obfs
|
||||
base64 = { version = "0.21", optional = true }
|
||||
base64 = { version = "0.22", optional = true }
|
||||
memchr = { version = "2", optional = true }
|
||||
|
||||
# Trojan
|
||||
@@ -239,7 +252,7 @@ jni = "0.21"
|
||||
# TUN
|
||||
[target.'cfg(any(target_os = "ios", target_os = "android", target_os = "macos", target_os = "linux"))'.dependencies]
|
||||
tun = { git = "https://github.com/eycorsican/rust-tun.git", branch = "fork", features = ["async"], optional = true }
|
||||
netstack-lwip = { git = "https://github.com/eycorsican/netstack-lwip.git", rev = "809a733", optional = true }
|
||||
netstack-lwip = { git = "https://github.com/eycorsican/netstack-lwip.git", rev = "9c7f2e3", optional = true }
|
||||
|
||||
[target.'cfg(any(target_os = "macos", target_os = "linux"))'.dependencies]
|
||||
pnet_datalink = { version = "0.34", package = "pnet_datalink", optional = true }
|
||||
@@ -250,11 +263,11 @@ libc = "0.2"
|
||||
memchr = { version = "2" }
|
||||
|
||||
[dev-dependencies]
|
||||
rcgen = "0.11"
|
||||
rcgen = "0.13"
|
||||
sha2 = "0.10"
|
||||
tokio = { version = "1", features = ["fs", "sync", "io-util", "net", "time", "rt", "rt-multi-thread"] }
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
bindgen = "0.68"
|
||||
protobuf-codegen = "=3.3.0"
|
||||
bindgen = "0.69"
|
||||
protobuf-codegen = "=3.4.0"
|
||||
|
||||
@@ -32,7 +32,7 @@ fn generate_mobile_bindings() {
|
||||
} else {
|
||||
"".to_string()
|
||||
})
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||
.generate()
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ pub(self) struct FakeDnsImpl {
|
||||
impl FakeDnsImpl {
|
||||
pub(self) fn new(mode: FakeDnsMode) -> Self {
|
||||
let min_cursor = Self::ip_to_u32(&Ipv4Addr::new(198, 18, 0, 0));
|
||||
let max_cursor = Self::ip_to_u32(&Ipv4Addr::new(198, 18, 4, 255));
|
||||
let max_cursor = Self::ip_to_u32(&Ipv4Addr::new(198, 18, 255, 255));
|
||||
Self {
|
||||
ip_to_domain: HashMap::new(),
|
||||
domain_to_ip: HashMap::new(),
|
||||
@@ -129,7 +129,7 @@ impl FakeDnsImpl {
|
||||
_ => return Err(anyhow!("unexpected Ipv6 fake IP")),
|
||||
}
|
||||
} else {
|
||||
let ip = self.allocate_ip(&domain);
|
||||
let ip = self.allocate_ip(&domain)?;
|
||||
debug!("allocate {} for {}", &ip, &domain);
|
||||
ip
|
||||
};
|
||||
@@ -173,30 +173,34 @@ impl FakeDnsImpl {
|
||||
ip >= self.min_cursor && ip <= self.max_cursor
|
||||
}
|
||||
|
||||
fn allocate_ip(&mut self, domain: &str) -> Ipv4Addr {
|
||||
fn allocate_ip(&mut self, domain: &str) -> Result<Ipv4Addr> {
|
||||
if let Some(prev_domain) = self.ip_to_domain.insert(self.cursor, domain.to_owned()) {
|
||||
// Remove the entry in the reverse map to make sure we won't have
|
||||
// multiple domains point to a same IP.
|
||||
self.domain_to_ip.remove(&prev_domain);
|
||||
}
|
||||
let ip = self.get_ip();
|
||||
self.domain_to_ip.insert(domain.to_owned(), self.cursor);
|
||||
self.cursor += 1;
|
||||
ip
|
||||
let ip = Self::u32_to_ip(self.cursor);
|
||||
self.prepare_next_cursor()?;
|
||||
Ok(ip)
|
||||
}
|
||||
|
||||
fn get_ip(&mut self) -> Ipv4Addr {
|
||||
if self.cursor > self.max_cursor {
|
||||
self.cursor = self.min_cursor;
|
||||
}
|
||||
let ip = Self::u32_to_ip(self.cursor);
|
||||
match ip.octets()[3] {
|
||||
0 | 255 => {
|
||||
self.cursor += 1;
|
||||
self.get_ip()
|
||||
// Make sure `self.cursor` is valid and can be used immediately for next fake IP.
|
||||
fn prepare_next_cursor(&mut self) -> Result<()> {
|
||||
for _ in 0..3 {
|
||||
self.cursor += 1;
|
||||
if self.cursor > self.max_cursor {
|
||||
self.cursor = self.min_cursor;
|
||||
}
|
||||
// avoid network and broadcast addresses
|
||||
match Self::u32_to_ip(self.cursor).octets()[3] {
|
||||
0 | 255 => {
|
||||
continue;
|
||||
}
|
||||
_ => return Ok(()),
|
||||
}
|
||||
_ => ip,
|
||||
}
|
||||
Err(anyhow!("unable to prepare next cursor"))
|
||||
}
|
||||
|
||||
fn accept(&self, domain: &str) -> bool {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This file is generated by rust-protobuf 3.3.0. Do not edit
|
||||
// .proto file is parsed by protoc 24.4
|
||||
// This file is generated by rust-protobuf 3.4.0. Do not edit
|
||||
// .proto file is parsed by protoc 26.1
|
||||
// @generated
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/702
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
/// Generated files are compatible only with the same version
|
||||
/// of protobuf runtime.
|
||||
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_3_0;
|
||||
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_4_0;
|
||||
|
||||
// @@protoc_insertion_point(message:SelectorCache)
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
|
||||
@@ -204,8 +204,11 @@ pub mod aead {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ring-aead")]
|
||||
#[cfg(any(feature = "aws-lc-aead", feature = "ring-aead"))]
|
||||
pub mod aead {
|
||||
#[cfg(feature = "aws-lc-aead")]
|
||||
use aws_lc_rs::aead::{self, Aad, Algorithm, LessSafeKey, Nonce, UnboundKey};
|
||||
#[cfg(feature = "ring-aead")]
|
||||
use ring::aead::{self, Aad, Algorithm, LessSafeKey, Nonce, UnboundKey};
|
||||
|
||||
use super::*;
|
||||
@@ -349,7 +352,11 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "ring-aead", feature = "openssl-aead"))]
|
||||
#[cfg(any(
|
||||
feature = "aws-lc-aead",
|
||||
feature = "ring-aead",
|
||||
feature = "openssl-aead"
|
||||
))]
|
||||
fn test_aead_enc_dec() {
|
||||
struct ShadowsocksNonceSequence(Vec<u8>);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This file is generated by rust-protobuf 3.3.0. Do not edit
|
||||
// .proto file is parsed by protoc 24.4
|
||||
// This file is generated by rust-protobuf 3.4.0. Do not edit
|
||||
// .proto file is parsed by protoc 26.1
|
||||
// @generated
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/702
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
/// Generated files are compatible only with the same version
|
||||
/// of protobuf runtime.
|
||||
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_3_0;
|
||||
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_4_0;
|
||||
|
||||
// @@protoc_insertion_point(message:Domain)
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This file is generated by rust-protobuf 3.3.0. Do not edit
|
||||
// .proto file is parsed by protoc 24.4
|
||||
// This file is generated by rust-protobuf 3.4.0. Do not edit
|
||||
// .proto file is parsed by protoc 26.1
|
||||
// @generated
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/702
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
/// Generated files are compatible only with the same version
|
||||
/// of protobuf runtime.
|
||||
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_3_0;
|
||||
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_4_0;
|
||||
|
||||
// @@protoc_insertion_point(message:Dns)
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
|
||||
@@ -59,8 +59,13 @@ pub struct StdOutboundDatagramSendHalf(Arc<UdpSocket>);
|
||||
#[async_trait]
|
||||
impl OutboundDatagramSendHalf for StdOutboundDatagramSendHalf {
|
||||
async fn send_to(&mut self, buf: &[u8], target: &SocksAddr) -> io::Result<usize> {
|
||||
// The type does not accept domain name.
|
||||
self.0.send_to(buf, target.must_ip()).await
|
||||
match target {
|
||||
SocksAddr::Ip(a) => self.0.send_to(buf, a).await,
|
||||
SocksAddr::Domain(domain, port) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("unexpected domain address {}:{}", domain, port),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
async fn close(&mut self) -> io::Result<()> {
|
||||
|
||||
@@ -22,7 +22,7 @@ use std::os::windows::io::{AsRawSocket, AsSocket};
|
||||
#[cfg(target_os = "android")]
|
||||
use {
|
||||
std::os::unix::io::RawFd, tokio::io::AsyncReadExt, tokio::io::AsyncWriteExt,
|
||||
tokio::net::UnixStream,
|
||||
tokio::net::UnixStream, tracing::trace,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
||||
@@ -8,6 +8,7 @@ use async_trait::async_trait;
|
||||
use futures::stream::Stream;
|
||||
use futures::task::{Context, Poll};
|
||||
use quinn::{RecvStream, SendStream};
|
||||
use rustls_pemfile_old::{certs, ec_private_keys, pkcs8_private_keys, rsa_private_keys};
|
||||
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
@@ -61,7 +62,7 @@ impl Handler {
|
||||
Some(Some(ext)) if ext == "der" => {
|
||||
vec![rustls::Certificate(cert)]
|
||||
}
|
||||
_ => rustls_pemfile::certs(&mut &*cert)?
|
||||
_ => certs(&mut &*cert)?
|
||||
.into_iter()
|
||||
.map(rustls::Certificate)
|
||||
.collect(),
|
||||
@@ -73,15 +74,15 @@ impl Handler {
|
||||
{
|
||||
Some(Some(ext)) if ext == "der" => rustls::PrivateKey(key),
|
||||
_ => {
|
||||
let pkcs8 = rustls_pemfile::pkcs8_private_keys(&mut &*key)?;
|
||||
let pkcs8 = pkcs8_private_keys(&mut &*key)?;
|
||||
match pkcs8.into_iter().next() {
|
||||
Some(x) => rustls::PrivateKey(x),
|
||||
None => {
|
||||
let rsa = rustls_pemfile::rsa_private_keys(&mut &*key)?;
|
||||
let rsa = rsa_private_keys(&mut &*key)?;
|
||||
match rsa.into_iter().next() {
|
||||
Some(x) => rustls::PrivateKey(x),
|
||||
None => {
|
||||
let rsa = rustls_pemfile::ec_private_keys(&mut &*key)?;
|
||||
let rsa = ec_private_keys(&mut &*key)?;
|
||||
match rsa.into_iter().next() {
|
||||
Some(x) => rustls::PrivateKey(x),
|
||||
None => {
|
||||
|
||||
@@ -8,6 +8,7 @@ use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
use futures::TryFutureExt;
|
||||
use rustls::OwnedTrustAnchor;
|
||||
use rustls_pemfile_old::certs;
|
||||
use tokio::sync::RwLock;
|
||||
use tracing::{debug, trace};
|
||||
|
||||
@@ -42,12 +43,11 @@ impl Manager {
|
||||
roots.add(&rustls::Certificate(cert)).unwrap(); // FIXME
|
||||
}
|
||||
_ => {
|
||||
let certs: Vec<rustls::Certificate> =
|
||||
rustls_pemfile::certs(&mut &*cert)
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(rustls::Certificate)
|
||||
.collect();
|
||||
let certs: Vec<rustls::Certificate> = certs(&mut &*cert)
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(rustls::Certificate)
|
||||
.collect();
|
||||
for cert in certs {
|
||||
roots.add(&cert).unwrap();
|
||||
}
|
||||
@@ -59,7 +59,7 @@ impl Manager {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
roots.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|ta| {
|
||||
roots.add_trust_anchors(webpki_roots_old::TLS_SERVER_ROOTS.iter().map(|ta| {
|
||||
OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||
ta.subject,
|
||||
ta.spki,
|
||||
|
||||
@@ -6,8 +6,11 @@ use anyhow::Result;
|
||||
|
||||
#[cfg(feature = "rustls-tls")]
|
||||
use {
|
||||
rustls_pemfile::{certs, pkcs8_private_keys, rsa_private_keys, ec_private_keys},
|
||||
tokio_rustls::rustls::{Certificate, PrivateKey, ServerConfig},
|
||||
rustls_pemfile::{certs, ec_private_keys, pkcs8_private_keys, rsa_private_keys},
|
||||
tokio_rustls::rustls::{
|
||||
pki_types::{CertificateDer, PrivateKeyDer},
|
||||
ServerConfig,
|
||||
},
|
||||
tokio_rustls::TlsAcceptor,
|
||||
};
|
||||
|
||||
@@ -19,23 +22,27 @@ pub struct Handler {
|
||||
}
|
||||
|
||||
#[cfg(feature = "rustls-tls")]
|
||||
fn load_certs(path: &Path) -> io::Result<Vec<Certificate>> {
|
||||
certs(&mut BufReader::new(File::open(path)?))
|
||||
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid cert"))
|
||||
.map(|mut certs| certs.drain(..).map(Certificate).collect())
|
||||
fn load_certs(path: &Path) -> io::Result<Vec<CertificateDer<'static>>> {
|
||||
certs(&mut BufReader::new(File::open(path)?)).collect()
|
||||
}
|
||||
|
||||
#[cfg(feature = "rustls-tls")]
|
||||
fn load_keys(path: &Path) -> io::Result<Vec<PrivateKey>> {
|
||||
let mut keys: Vec<PrivateKey> = pkcs8_private_keys(&mut BufReader::new(File::open(path)?))
|
||||
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key"))
|
||||
.map(|mut keys| keys.drain(..).map(PrivateKey).collect())?;
|
||||
let mut keys2: Vec<PrivateKey> = rsa_private_keys(&mut BufReader::new(File::open(path)?))
|
||||
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key"))
|
||||
.map(|mut keys| keys.drain(..).map(PrivateKey).collect())?;
|
||||
let mut keys3: Vec<PrivateKey> = ec_private_keys(&mut BufReader::new(File::open(path)?))
|
||||
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key"))
|
||||
.map(|mut keys| keys.drain(..).map(PrivateKey).collect())?;
|
||||
fn load_keys(path: &Path) -> io::Result<Vec<PrivateKeyDer<'static>>> {
|
||||
let mut keys = pkcs8_private_keys(&mut BufReader::new(File::open(path)?))
|
||||
.into_iter()
|
||||
.filter_map(|x| x.ok())
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>();
|
||||
let mut keys2 = rsa_private_keys(&mut BufReader::new(File::open(path)?))
|
||||
.into_iter()
|
||||
.filter_map(|x| x.ok())
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>();
|
||||
let mut keys3 = ec_private_keys(&mut BufReader::new(File::open(path)?))
|
||||
.into_iter()
|
||||
.filter_map(|x| x.ok())
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>();
|
||||
keys.append(&mut keys3);
|
||||
keys.append(&mut keys2);
|
||||
Ok(keys)
|
||||
@@ -48,7 +55,6 @@ impl Handler {
|
||||
let certs = load_certs(Path::new(&certificate))?;
|
||||
let mut keys = load_keys(Path::new(&certificate_key))?;
|
||||
let config = ServerConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(certs, keys.remove(0))
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?;
|
||||
|
||||
@@ -11,7 +11,7 @@ use tracing::trace;
|
||||
use {
|
||||
std::sync::Arc,
|
||||
tokio_rustls::{
|
||||
rustls::{Certificate, ClientConfig, OwnedTrustAnchor, RootCertStore, ServerName},
|
||||
rustls::{pki_types::ServerName, ClientConfig, RootCertStore},
|
||||
TlsConnector,
|
||||
},
|
||||
};
|
||||
@@ -28,26 +28,63 @@ use crate::{proxy::*, session::Session};
|
||||
|
||||
#[cfg(feature = "rustls-tls")]
|
||||
mod dangerous {
|
||||
use std::time::SystemTime;
|
||||
use tokio_rustls::rustls::{
|
||||
client::{ServerCertVerified, ServerCertVerifier},
|
||||
Certificate, Error, ServerName,
|
||||
client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
|
||||
pki_types::{CertificateDer, ServerName, UnixTime},
|
||||
DigitallySignedStruct, Error, SignatureScheme,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct NotVerified;
|
||||
|
||||
impl ServerCertVerifier for NotVerified {
|
||||
fn verify_server_cert(
|
||||
&self,
|
||||
_end_entity: &Certificate,
|
||||
_intermediates: &[Certificate],
|
||||
_end_entity: &CertificateDer,
|
||||
_intermediates: &[CertificateDer],
|
||||
_server_name: &ServerName,
|
||||
_scts: &mut dyn Iterator<Item = &[u8]>,
|
||||
_ocsp_response: &[u8],
|
||||
_now: SystemTime,
|
||||
_now: UnixTime,
|
||||
) -> core::result::Result<ServerCertVerified, Error> {
|
||||
Ok(ServerCertVerified::assertion())
|
||||
}
|
||||
|
||||
fn verify_tls12_signature(
|
||||
&self,
|
||||
_message: &[u8],
|
||||
_cert: &CertificateDer<'_>,
|
||||
_dss: &DigitallySignedStruct,
|
||||
) -> Result<HandshakeSignatureValid, Error> {
|
||||
Ok(HandshakeSignatureValid::assertion())
|
||||
}
|
||||
|
||||
fn verify_tls13_signature(
|
||||
&self,
|
||||
_message: &[u8],
|
||||
_cert: &CertificateDer<'_>,
|
||||
_dss: &DigitallySignedStruct,
|
||||
) -> Result<HandshakeSignatureValid, Error> {
|
||||
Ok(HandshakeSignatureValid::assertion())
|
||||
}
|
||||
|
||||
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
|
||||
// Non-exhaustive, new variants can be added in the future.
|
||||
vec![
|
||||
SignatureScheme::RSA_PKCS1_SHA1,
|
||||
SignatureScheme::ECDSA_SHA1_Legacy,
|
||||
SignatureScheme::RSA_PKCS1_SHA256,
|
||||
SignatureScheme::ECDSA_NISTP256_SHA256,
|
||||
SignatureScheme::RSA_PKCS1_SHA384,
|
||||
SignatureScheme::ECDSA_NISTP384_SHA384,
|
||||
SignatureScheme::RSA_PKCS1_SHA512,
|
||||
SignatureScheme::ECDSA_NISTP521_SHA512,
|
||||
SignatureScheme::RSA_PSS_SHA256,
|
||||
SignatureScheme::RSA_PSS_SHA384,
|
||||
SignatureScheme::RSA_PSS_SHA512,
|
||||
SignatureScheme::ED25519,
|
||||
SignatureScheme::ED448,
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,27 +105,17 @@ impl Handler {
|
||||
) -> Result<Self> {
|
||||
#[cfg(feature = "rustls-tls")]
|
||||
{
|
||||
let mut root_cert_store = RootCertStore::empty();
|
||||
let mut roots = RootCertStore::empty();
|
||||
if let Some(cert) = certificate {
|
||||
let mut pem = BufReader::new(File::open(cert)?);
|
||||
let certs = rustls_pemfile::certs(&mut pem)?;
|
||||
for cert in certs.into_iter().map(Certificate) {
|
||||
root_cert_store.add(&cert)?;
|
||||
for cert in rustls_pemfile::certs(&mut pem) {
|
||||
roots.add(cert?)?;
|
||||
}
|
||||
} else {
|
||||
root_cert_store.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(
|
||||
|ta| {
|
||||
OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||
ta.subject,
|
||||
ta.spki,
|
||||
ta.name_constraints,
|
||||
)
|
||||
},
|
||||
));
|
||||
roots.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
||||
}
|
||||
let mut config = ClientConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_root_certificates(root_cert_store)
|
||||
.with_root_certificates(roots)
|
||||
.with_no_client_auth();
|
||||
if insecure {
|
||||
let mut dangerous_config = config.dangerous();
|
||||
@@ -160,7 +187,7 @@ impl OutboundStreamHandler for Handler {
|
||||
)
|
||||
})?;
|
||||
let tls_stream = connector
|
||||
.connect(domain, stream)
|
||||
.connect(domain.to_owned(), stream)
|
||||
.map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
|
||||
@@ -189,11 +189,12 @@ fn test_quic_trojan() {
|
||||
|
||||
let mut path = std::env::current_exe().unwrap();
|
||||
path.pop();
|
||||
let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap();
|
||||
std::fs::write(&path.join("key.der"), &cert.serialize_private_key_der()).unwrap();
|
||||
std::fs::write(&path.join("cert.der"), &cert.serialize_der().unwrap()).unwrap();
|
||||
std::fs::write(&path.join("key.pem"), &cert.serialize_private_key_pem()).unwrap();
|
||||
std::fs::write(&path.join("cert.pem"), &cert.serialize_pem().unwrap()).unwrap();
|
||||
let rcgen::CertifiedKey { cert, key_pair } =
|
||||
rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap();
|
||||
std::fs::write(&path.join("key.der"), &key_pair.serialize_der()).unwrap();
|
||||
std::fs::write(&path.join("cert.der"), &cert.der().to_vec()).unwrap();
|
||||
std::fs::write(&path.join("key.pem"), &key_pair.serialize_pem()).unwrap();
|
||||
std::fs::write(&path.join("cert.pem"), &cert.pem()).unwrap();
|
||||
|
||||
let configs = vec![config1.to_string(), config2.to_string()];
|
||||
common::test_configs(configs.clone(), "127.0.0.1", 1086);
|
||||
|
||||
@@ -176,11 +176,12 @@ fn test_tls_trojan() {
|
||||
|
||||
let mut path = std::env::current_exe().unwrap();
|
||||
path.pop();
|
||||
let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap();
|
||||
std::fs::write(&path.join("key.der"), &cert.serialize_private_key_der()).unwrap();
|
||||
std::fs::write(&path.join("cert.der"), &cert.serialize_der().unwrap()).unwrap();
|
||||
std::fs::write(&path.join("key.pem"), &cert.serialize_private_key_pem()).unwrap();
|
||||
std::fs::write(&path.join("cert.pem"), &cert.serialize_pem().unwrap()).unwrap();
|
||||
let rcgen::CertifiedKey { cert, key_pair } =
|
||||
rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap();
|
||||
std::fs::write(&path.join("key.der"), &key_pair.serialize_der()).unwrap();
|
||||
std::fs::write(&path.join("cert.der"), &cert.der().to_vec()).unwrap();
|
||||
std::fs::write(&path.join("key.pem"), &key_pair.serialize_pem()).unwrap();
|
||||
std::fs::write(&path.join("cert.pem"), &cert.pem()).unwrap();
|
||||
let configs = vec![config1.to_string(), config2.to_string()];
|
||||
common::test_configs(configs, "127.0.0.1", 1086);
|
||||
let configs = vec![config3.to_string(), config4.to_string()];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -x
|
||||
set -ex
|
||||
|
||||
name=leaf
|
||||
package=leaf-ffi
|
||||
@@ -24,7 +24,9 @@ fi
|
||||
|
||||
BASE=`dirname "$0"`
|
||||
HOST_OS=`uname -s | tr "[:upper:]" "[:lower:]"`
|
||||
HOST_ARCH=`uname -m | tr "[:upper:]" "[:lower:]"`
|
||||
|
||||
# HOST_ARCH=`uname -m | tr "[:upper:]" "[:lower:]"`
|
||||
HOST_ARCH=x86_64
|
||||
|
||||
export PATH="$NDK_HOME/toolchains/llvm/prebuilt/$HOST_OS-$HOST_ARCH/bin/":$PATH
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -x
|
||||
set -ex
|
||||
|
||||
mode=release
|
||||
release_flag=--release
|
||||
@@ -17,17 +17,20 @@ if [ "$1" = "debug" ]; then
|
||||
release_flag=
|
||||
fi
|
||||
|
||||
export IPHONEOS_DEPLOYMENT_TARGET=10.0
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.12
|
||||
|
||||
# Build for all desired targets
|
||||
rustup target add x86_64-apple-darwin
|
||||
rustup target add aarch64-apple-darwin
|
||||
rustup target add aarch64-apple-ios
|
||||
rustup target add x86_64-apple-ios
|
||||
rustup target add aarch64-apple-ios-sim
|
||||
cargo build -p $package $release_flag --no-default-features --features "default-openssl outbound-quic" --target x86_64-apple-darwin
|
||||
cargo build -p $package $release_flag --no-default-features --features "default-openssl outbound-quic" --target aarch64-apple-darwin
|
||||
cargo build -p $package $release_flag --no-default-features --features "default-openssl outbound-quic" --target aarch64-apple-ios
|
||||
cargo build -p $package $release_flag --no-default-features --features "default-openssl outbound-quic" --target x86_64-apple-ios
|
||||
cargo build -p $package $release_flag --no-default-features --features "default-ring outbound-quic" --target aarch64-apple-ios-sim
|
||||
cargo build -p $package $release_flag --no-default-features --features "default-aws-lc outbound-quic" --target x86_64-apple-darwin
|
||||
cargo build -p $package $release_flag --no-default-features --features "default-aws-lc outbound-quic" --target aarch64-apple-darwin
|
||||
cargo build -p $package $release_flag --no-default-features --features "default-aws-lc outbound-quic" --target aarch64-apple-ios
|
||||
cargo build -p $package $release_flag --no-default-features --features "default-aws-lc outbound-quic" --target x86_64-apple-ios
|
||||
cargo build -p $package $release_flag --no-default-features --features "default-aws-lc outbound-quic" --target aarch64-apple-ios-sim
|
||||
|
||||
cargo install --force cbindgen
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
target=$1
|
||||
|
||||
if [[ "$target" == *"mips"* ]]; then
|
||||
cross build --release --target $target --manifest-path leaf-bin/Cargo.toml --no-default-features --features "default-openssl"
|
||||
else
|
||||
cross build --release --target $target --manifest-path leaf-bin/Cargo.toml --no-default-features --features "default-ring"
|
||||
fi
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -x
|
||||
set -ex
|
||||
|
||||
touch leaf/build.rs
|
||||
PROTO_GEN=1 cargo build -p leaf
|
||||
|
||||
Reference in New Issue
Block a user