trust-dns setsockopt with outbound socket configs

Outbound configurations, like outbound-fwmark, outbound-bind-interface,
         outbound-bind-addr, ... will also applies to the TCP/UDP
         sockets created by trust-dns DNS resolver.

NOTE: On Android platform, DNS sockets will also be protected.
This commit is contained in:
zonyitoo
2023-04-15 17:28:15 +08:00
committed by ty
parent c1f505ff7b
commit 2dff4ec4da
17 changed files with 326 additions and 197 deletions
Generated
+87 -105
View File
@@ -72,42 +72,51 @@ dependencies = [
[[package]]
name = "anstream"
version = "0.2.6"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f"
checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"concolor-override",
"concolor-query",
"colorchoice",
"is-terminal",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "0.3.5"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2"
checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
[[package]]
name = "anstyle-parse"
version = "0.1.1"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116"
checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-wincon"
version = "0.2.0"
name = "anstyle-query"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "anstyle-wincon"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd"
dependencies = [
"anstyle",
"windows-sys 0.45.0",
"windows-sys 0.48.0",
]
[[package]]
@@ -142,7 +151,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.13",
"syn 2.0.15",
]
[[package]]
@@ -343,18 +352,18 @@ dependencies = [
[[package]]
name = "clap"
version = "4.2.1"
version = "4.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3"
checksum = "9b802d85aaf3a1cdb02b224ba472ebdea62014fccfcb269b95a4d76443b5ee5a"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.2.1"
version = "4.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f"
checksum = "14a1a858f532119338887a4b8e1af9c60de8249cd7bafd68036a489e261e37b6"
dependencies = [
"anstream",
"anstyle",
@@ -390,19 +399,10 @@ dependencies = [
]
[[package]]
name = "concolor-override"
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f"
[[package]]
name = "concolor-query"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf"
dependencies = [
"windows-sys 0.45.0",
]
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "const-oid"
@@ -449,9 +449,9 @@ checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
[[package]]
name = "crossbeam-channel"
version = "0.5.7"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [
"cfg-if",
"crossbeam-utils",
@@ -522,7 +522,7 @@ dependencies = [
"proc-macro2",
"quote",
"scratch",
"syn 2.0.13",
"syn 2.0.15",
]
[[package]]
@@ -539,7 +539,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.13",
"syn 2.0.15",
]
[[package]]
@@ -559,9 +559,9 @@ checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb"
[[package]]
name = "defmt"
version = "0.3.3"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d03193cde597714ff8a5005ccd61cd1b7aff5616eaca7c67905982cb6f347ff4"
checksum = "956673bd3cb347512bf988d1e8d89ac9a82b64f6eec54d3c01c3529dac019882"
dependencies = [
"bitflags",
"defmt-macros",
@@ -731,13 +731,13 @@ dependencies = [
[[package]]
name = "errno"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
"windows-sys 0.45.0",
"windows-sys 0.48.0",
]
[[package]]
@@ -770,14 +770,14 @@ dependencies = [
[[package]]
name = "filetime"
version = "0.2.20"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412"
checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.2.16",
"windows-sys 0.45.0",
"windows-sys 0.48.0",
]
[[package]]
@@ -875,7 +875,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.13",
"syn 2.0.15",
]
[[package]]
@@ -920,9 +920,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.8"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
dependencies = [
"cfg-if",
"libc",
@@ -941,9 +941,9 @@ dependencies = [
[[package]]
name = "h2"
version = "0.3.16"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d"
checksum = "66b91535aa35fea1523ad1b86cb6b53c28e0ae566ba4a460f4457e936cad7c6f"
dependencies = [
"bytes",
"fnv",
@@ -1078,9 +1078,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
version = "0.14.25"
version = "0.14.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899"
checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4"
dependencies = [
"bytes",
"futures-channel",
@@ -1124,17 +1124,6 @@ dependencies = [
"cxx-build",
]
[[package]]
name = "idna"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "idna"
version = "0.3.0"
@@ -1195,13 +1184,13 @@ dependencies = [
[[package]]
name = "io-lifetimes"
version = "1.0.9"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
dependencies = [
"hermit-abi 0.3.1",
"libc",
"windows-sys 0.45.0",
"windows-sys 0.48.0",
]
[[package]]
@@ -1239,14 +1228,14 @@ dependencies = [
[[package]]
name = "is-terminal"
version = "0.4.6"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8"
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys 0.45.0",
"windows-sys 0.48.0",
]
[[package]]
@@ -1437,12 +1426,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]]
name = "matches"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]]
name = "md-5"
version = "0.10.5"
@@ -1581,9 +1564,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "openssl"
version = "0.10.49"
version = "0.10.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d2f106ab837a24e03672c59b1239669a0596406ff657c3c0835b6b7f0f35a33"
checksum = "7e30d8bc91859781f0a943411186324d580f2bbeb71b452fe91ae344806af3f1"
dependencies = [
"bitflags",
"cfg-if",
@@ -1602,7 +1585,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.13",
"syn 2.0.15",
]
[[package]]
@@ -1613,9 +1596,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.84"
version = "0.9.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a20eace9dc2d82904039cb76dcf50fb1a0bba071cfd1629720b5d6f1ddba0fa"
checksum = "0d3d193fb1488ad46ffe3aaabc912cc931d02ee8518fe2959aea8ef52718b0c0"
dependencies = [
"cc",
"libc",
@@ -1711,7 +1694,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.13",
"syn 2.0.15",
]
[[package]]
@@ -2031,16 +2014,16 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.37.7"
version = "0.37.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d"
checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys 0.45.0",
"windows-sys 0.48.0",
]
[[package]]
@@ -2198,9 +2181,9 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.159"
version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
dependencies = [
"serde_derive",
]
@@ -2217,20 +2200,20 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.159"
version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"
checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.13",
"syn 2.0.15",
]
[[package]]
name = "serde_json"
version = "1.0.95"
version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744"
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
dependencies = [
"itoa",
"ryu",
@@ -2285,7 +2268,7 @@ dependencies = [
[[package]]
name = "shadowsocks"
version = "1.15.3"
version = "1.16.0"
dependencies = [
"aes",
"arc-swap",
@@ -2311,7 +2294,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"shadowsocks-crypto",
"socket2 0.5.1",
"socket2 0.5.2",
"spin 0.9.8",
"thiserror",
"tokio",
@@ -2346,7 +2329,7 @@ dependencies = [
[[package]]
name = "shadowsocks-rust"
version = "1.15.3"
version = "1.16.0"
dependencies = [
"base64",
"build-time",
@@ -2382,7 +2365,7 @@ dependencies = [
[[package]]
name = "shadowsocks-service"
version = "1.15.3"
version = "1.16.0"
dependencies = [
"arc-swap",
"async-trait",
@@ -2394,7 +2377,7 @@ dependencies = [
"etherparse",
"futures",
"hyper",
"idna 0.3.0",
"idna",
"ipnet",
"iprange",
"json5",
@@ -2411,7 +2394,7 @@ dependencies = [
"serde",
"shadowsocks",
"smoltcp",
"socket2 0.5.1",
"socket2 0.5.2",
"spin 0.9.8",
"thiserror",
"tokio",
@@ -2508,12 +2491,12 @@ dependencies = [
[[package]]
name = "socket2"
version = "0.5.1"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc8d618c6641ae355025c449427f9e96b98abf99a772be3cef6708d15c77147a"
checksum = "6d283f86695ae989d1e18440a943880967156325ba025f05049946bff47bcc2b"
dependencies = [
"libc",
"windows-sys 0.45.0",
"windows-sys 0.48.0",
]
[[package]]
@@ -2578,9 +2561,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.13"
version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec"
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
dependencies = [
"proc-macro2",
"quote",
@@ -2657,7 +2640,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.13",
"syn 2.0.15",
]
[[package]]
@@ -2724,7 +2707,7 @@ checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.13",
"syn 2.0.15",
]
[[package]]
@@ -2862,8 +2845,7 @@ dependencies = [
[[package]]
name = "trust-dns-proto"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26"
source = "git+https://github.com/bluejekyll/trust-dns.git#c551ebb45a4a15343b8305193fece2e5c23a84ed"
dependencies = [
"async-trait",
"bytes",
@@ -2875,7 +2857,7 @@ dependencies = [
"futures-util",
"h2",
"http",
"idna 0.2.3",
"idna",
"ipnet",
"lazy_static",
"rand",
@@ -2896,8 +2878,7 @@ dependencies = [
[[package]]
name = "trust-dns-resolver"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe"
source = "git+https://github.com/bluejekyll/trust-dns.git#c551ebb45a4a15343b8305193fece2e5c23a84ed"
dependencies = [
"cfg-if",
"futures-util",
@@ -2905,6 +2886,7 @@ dependencies = [
"lazy_static",
"lru-cache",
"parking_lot",
"rand",
"resolv-conf",
"rustls 0.20.8",
"serde",
@@ -3019,7 +3001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
dependencies = [
"form_urlencoded",
"idna 0.3.0",
"idna",
"percent-encoding",
"serde",
]
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "shadowsocks-rust"
version = "1.15.3"
version = "1.16.0"
authors = ["Shadowsocks Contributors"]
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
repository = "https://github.com/shadowsocks/shadowsocks-rust"
@@ -167,7 +167,7 @@ jemallocator = { version = "0.5", optional = true }
snmalloc-rs = { version = "0.3", optional = true }
rpmalloc = { version = "0.2", optional = true }
shadowsocks-service = { version = "1.15.0", path = "./crates/shadowsocks-service" }
shadowsocks-service = { version = "1.16.0", path = "./crates/shadowsocks-service" }
[target.'cfg(unix)'.dependencies]
daemonize = "0.5"
+4 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "shadowsocks-service"
version = "1.15.3"
version = "1.16.0"
authors = ["Shadowsocks Contributors"]
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
repository = "https://github.com/shadowsocks/shadowsocks-rust"
@@ -107,7 +107,8 @@ libc = "0.2.141"
hyper = { version = "0.14.25", optional = true, features = ["full"] }
tower = { version = "0.4", optional = true }
trust-dns-resolver = { version = "0.22", optional = true, features = ["serde-config"] }
# trust-dns-resolver = { version = "0.22", optional = true, features = ["serde-config"] }
trust-dns-resolver = { git = "https://github.com/bluejekyll/trust-dns.git", optional = true, features = ["serde-config"] }
idna = "0.3"
ipnet = "2.7"
@@ -121,7 +122,7 @@ smoltcp = { version = "0.9", optional = true, default-features = false, features
serde = { version = "1.0", features = ["derive"] }
json5 = "0.4"
shadowsocks = { version = "1.15.3", path = "../shadowsocks", default-features = false }
shadowsocks = { version = "1.16.0", path = "../shadowsocks", default-features = false }
# Just for the ioctl call macro
[target.'cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))'.dependencies]
+4 -18
View File
@@ -2112,26 +2112,12 @@ impl Config {
};
if protocol.enable_udp() {
c.add_name_server(NameServerConfig {
socket_addr,
protocol: Protocol::Udp,
tls_dns_name: None,
trust_nx_responses: false,
#[cfg(any(feature = "dns-over-tls", feature = "dns-over-https"))]
tls_config: None,
bind_addr: None,
});
let ns_config = NameServerConfig::new(socket_addr, Protocol::Udp);
c.add_name_server(ns_config);
}
if protocol.enable_tcp() {
c.add_name_server(NameServerConfig {
socket_addr,
protocol: Protocol::Tcp,
tls_dns_name: None,
trust_nx_responses: false,
#[cfg(any(feature = "dns-over-tls", feature = "dns-over-https"))]
tls_config: None,
bind_addr: None,
});
let ns_config = NameServerConfig::new(socket_addr, Protocol::Tcp);
c.add_name_server(ns_config);
}
}
+2 -2
View File
@@ -23,7 +23,7 @@ pub async fn build_dns_resolver(dns: DnsConfig, ipv6_first: bool, connect_opts:
};
if !force_system_builtin {
return match DnsResolver::trust_dns_system_resolver(ipv6_first).await {
return match DnsResolver::trust_dns_system_resolver(connect_opts.clone()).await {
Ok(r) => Some(r),
Err(err) => {
warn!(
@@ -41,7 +41,7 @@ pub async fn build_dns_resolver(dns: DnsConfig, ipv6_first: bool, connect_opts:
None
}
#[cfg(feature = "trust-dns")]
DnsConfig::TrustDns(dns) => match DnsResolver::trust_dns_resolver(dns, ipv6_first).await {
DnsConfig::TrustDns(dns) => match DnsResolver::trust_dns_resolver(dns, connect_opts.clone()).await {
Ok(r) => Some(r),
Err(err) => {
use log::warn;
@@ -2,7 +2,7 @@
use std::{
io::{self, ErrorKind},
net::SocketAddr,
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
};
use async_trait::async_trait;
@@ -175,8 +175,8 @@ fn store_dns(res: Message, port: u16) -> Vec<SocketAddr> {
let mut vaddr = Vec::new();
for record in res.answers() {
match record.data() {
Some(RData::A(addr)) => vaddr.push(SocketAddr::new((*addr).into(), port)),
Some(RData::AAAA(addr)) => vaddr.push(SocketAddr::new((*addr).into(), port)),
Some(RData::A(addr)) => vaddr.push(SocketAddr::new(Ipv4Addr::from(*addr).into(), port)),
Some(RData::AAAA(addr)) => vaddr.push(SocketAddr::new(Ipv6Addr::from(*addr).into(), port)),
Some(rdata) => {
trace!("skipped rdata {:?}", rdata);
}
@@ -413,8 +413,8 @@ fn should_forward_by_response(
return true;
}
let forward = match $rec.data() {
Some(RData::A(ip)) => acl.check_ip_in_proxy_list(&IpAddr::V4(*ip)),
Some(RData::AAAA(ip)) => acl.check_ip_in_proxy_list(&IpAddr::V6(*ip)),
Some(RData::A(ip)) => acl.check_ip_in_proxy_list(&IpAddr::V4((*ip).into())),
Some(RData::AAAA(ip)) => acl.check_ip_in_proxy_list(&IpAddr::V6((*ip).into())),
// MX records cause type A additional section processing for the host specified by EXCHANGE.
Some(RData::MX(mx)) => examine_name!(mx.exchange(), $is_answer),
// NS records cause both the usual additional section processing to locate a type A record...
@@ -498,8 +498,16 @@ impl DnsClient {
for rec in result.answers() {
trace!("dns answer: {:?}", rec);
match rec.data() {
Some(RData::A(ip)) => self.context.add_to_reverse_lookup_cache((*ip).into(), forward).await,
Some(RData::AAAA(ip)) => self.context.add_to_reverse_lookup_cache((*ip).into(), forward).await,
Some(RData::A(ip)) => {
self.context
.add_to_reverse_lookup_cache(Ipv4Addr::from(*ip).into(), forward)
.await
}
Some(RData::AAAA(ip)) => {
self.context
.add_to_reverse_lookup_cache(Ipv6Addr::from(*ip).into(), forward)
.await
}
_ => (),
}
}
+3 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "shadowsocks"
version = "1.15.3"
version = "1.16.0"
authors = ["Shadowsocks Contributors"]
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
repository = "https://github.com/shadowsocks/shadowsocks-rust"
@@ -68,7 +68,8 @@ socket2 = { version = "0.5", features = ["all"] }
tokio = { version = "1.9.0", features = ["io-util", "macros", "net", "parking_lot", "process", "rt", "sync", "time"] }
tokio-tfo = "0.2.0"
trust-dns-resolver = { version = "0.22", optional = true }
# trust-dns-resolver = { version = "0.22", optional = true }
trust-dns-resolver = { git = "https://github.com/bluejekyll/trust-dns.git", optional = true }
arc-swap = { version = "1.6", optional = true }
notify = { version = "5.1.0", optional = true }
+33 -25
View File
@@ -20,7 +20,13 @@ use tokio::net::lookup_host;
#[cfg(feature = "trust-dns")]
use tokio::task::JoinHandle;
#[cfg(feature = "trust-dns")]
use trust_dns_resolver::{config::ResolverConfig, TokioAsyncResolver};
use trust_dns_resolver::config::ResolverConfig;
#[cfg(feature = "trust-dns")]
use crate::net::ConnectOpts;
#[cfg(feature = "trust-dns")]
use super::trust_dns_resolver::DnsResolver as TrustDnsResolver;
/// Abstract DNS resolver
#[async_trait]
@@ -31,8 +37,8 @@ pub trait DnsResolve {
#[cfg(feature = "trust-dns")]
pub struct TrustDnsSystemResolver {
resolver: ArcSwap<TokioAsyncResolver>,
ipv6_first: bool,
resolver: ArcSwap<TrustDnsResolver>,
connect_opts: ConnectOpts,
}
/// Collections of DNS resolver
@@ -44,11 +50,12 @@ pub enum DnsResolver {
#[cfg(feature = "trust-dns")]
TrustDnsSystem {
inner: Arc<TrustDnsSystemResolver>,
#[cfg(all(feature = "trust-dns", unix, not(target_os = "android")))]
abortable: JoinHandle<()>,
},
/// Trust-DNS resolver
#[cfg(feature = "trust-dns")]
TrustDns(TokioAsyncResolver),
TrustDns(TrustDnsResolver),
/// Customized Resolver
Custom(Box<dyn DnsResolve + Send + Sync>),
}
@@ -75,6 +82,7 @@ impl Debug for DnsResolver {
#[cfg(feature = "trust-dns")]
impl Drop for DnsResolver {
fn drop(&mut self) {
#[cfg(all(feature = "trust-dns", unix, not(target_os = "android")))]
if let DnsResolver::TrustDnsSystem { ref abortable, .. } = *self {
abortable.abort();
}
@@ -187,7 +195,7 @@ async fn trust_dns_notify_update_dns(resolver: Arc<TrustDnsSystemResolver>) -> n
// Update once for all those Modify events
time::sleep(Duration::from_secs(1)).await;
match create_resolver(None, resolver.ipv6_first).await {
match create_resolver(None, resolver.connect_opts.clone()).await {
Ok(r) => {
debug!("auto-reload {DNS_RESOLV_FILE_PATH}");
@@ -208,12 +216,6 @@ async fn trust_dns_notify_update_dns(resolver: Arc<TrustDnsSystemResolver>) -> n
Ok(())
}
#[cfg(all(feature = "trust-dns", any(not(unix), target_os = "android")))]
async fn trust_dns_notify_update_dns(resolver: Arc<TrustDnsSystemResolver>) -> notify::Result<()> {
let _ = resolver.ipv6_first; // use it for supressing warning
futures::future::pending().await
}
impl DnsResolver {
/// Use system DNS resolver. Tokio will call `getaddrinfo` in blocking pool.
pub fn system_resolver() -> DnsResolver {
@@ -224,33 +226,39 @@ impl DnsResolver {
///
/// On *nix system, it will try to read configurations from `/etc/resolv.conf`.
#[cfg(feature = "trust-dns")]
pub async fn trust_dns_system_resolver(ipv6_first: bool) -> io::Result<DnsResolver> {
pub async fn trust_dns_system_resolver(connect_opts: ConnectOpts) -> io::Result<DnsResolver> {
use super::trust_dns_resolver::create_resolver;
let resolver = create_resolver(None, ipv6_first).await?;
let resolver = create_resolver(None, connect_opts.clone()).await?;
let inner = Arc::new(TrustDnsSystemResolver {
resolver: ArcSwap::from(Arc::new(resolver)),
ipv6_first,
connect_opts,
});
let abortable = {
let inner = inner.clone();
tokio::spawn(async {
if let Err(err) = trust_dns_notify_update_dns(inner).await {
error!("failed to watch DNS system configuration changes, error: {}", err);
}
})
};
cfg_if! {
if #[cfg(all(feature = "trust-dns", unix, not(target_os = "android")))] {
let abortable = {
let inner = inner.clone();
tokio::spawn(async {
if let Err(err) = trust_dns_notify_update_dns(inner).await {
error!("failed to watch DNS system configuration changes, error: {}", err);
}
})
};
Ok(DnsResolver::TrustDnsSystem { inner, abortable })
Ok(DnsResolver::TrustDnsSystem { inner, abortable })
} else {
Ok(DnsResolver::TrustDnsSystem { inner })
}
}
}
/// Use trust-dns DNS resolver (with DNS cache)
#[cfg(feature = "trust-dns")]
pub async fn trust_dns_resolver(dns: ResolverConfig, ipv6_first: bool) -> io::Result<DnsResolver> {
pub async fn trust_dns_resolver(dns: ResolverConfig, connect_opts: ConnectOpts) -> io::Result<DnsResolver> {
use super::trust_dns_resolver::create_resolver;
Ok(DnsResolver::TrustDns(create_resolver(Some(dns), ipv6_first).await?))
Ok(DnsResolver::TrustDns(create_resolver(Some(dns), connect_opts).await?))
}
/// Custom DNS resolver
@@ -1,15 +1,102 @@
//! Asynchronous DNS resolver
use std::{
future::Future,
io,
net::SocketAddr,
ops::Deref,
pin::Pin,
task::{Context, Poll},
};
use cfg_if::cfg_if;
use futures::ready;
use log::trace;
use tokio::{io::ReadBuf, net::UdpSocket};
use trust_dns_resolver::{
config::{LookupIpStrategy, ResolverConfig, ResolverOpts},
error::ResolveResult,
TokioAsyncResolver,
name_server::RuntimeProvider,
proto::{iocompat::AsyncIoTokioAsStd, udp::DnsUdpSocket, TokioTime},
AsyncResolver,
TokioHandle,
};
use crate::net::{tcp::TcpStream as ShadowTcpStream, udp::UdpSocket as ShadowUdpSocket, ConnectOpts};
/// Shadowsocks trust-dns Runtime Provider
#[derive(Clone)]
pub struct ShadowDnsProvider {
handle: TokioHandle,
connect_opts: ConnectOpts,
}
impl ShadowDnsProvider {
fn new(connect_opts: ConnectOpts) -> ShadowDnsProvider {
ShadowDnsProvider {
handle: TokioHandle::default(),
connect_opts,
}
}
}
impl DnsUdpSocket for ShadowUdpSocket {
type Time = TokioTime;
#[inline]
fn poll_recv_from(&self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<io::Result<(usize, SocketAddr)>> {
let udp: &UdpSocket = self.deref();
let mut read_buf = ReadBuf::new(buf);
let recv_addr = ready!(udp.poll_recv_from(cx, &mut read_buf))?;
Ok((read_buf.filled().len(), recv_addr)).into()
}
#[inline]
fn poll_send_to(&self, cx: &mut Context<'_>, buf: &[u8], target: SocketAddr) -> Poll<io::Result<usize>> {
let udp: &UdpSocket = self.deref();
udp.poll_send_to(cx, buf, target)
}
}
impl RuntimeProvider for ShadowDnsProvider {
type Handle = TokioHandle;
type Tcp = AsyncIoTokioAsStd<ShadowTcpStream>;
type Timer = TokioTime;
type Udp = ShadowUdpSocket;
fn create_handle(&self) -> Self::Handle {
self.handle.clone()
}
fn connect_tcp(&self, server_addr: SocketAddr) -> Pin<Box<dyn Send + Future<Output = io::Result<Self::Tcp>>>> {
let connect_opts = self.connect_opts.clone();
Box::pin(async move {
let tcp = ShadowTcpStream::connect_with_opts(&server_addr, &connect_opts).await?;
Ok(AsyncIoTokioAsStd(tcp))
})
}
fn bind_udp(
&self,
local_addr: SocketAddr,
_server_addr: SocketAddr,
) -> Pin<Box<dyn Send + Future<Output = std::io::Result<Self::Udp>>>> {
let connect_opts = self.connect_opts.clone();
Box::pin(async move {
let udp = ShadowUdpSocket::bind_with_opts(&local_addr, &connect_opts).await?;
Ok(udp)
})
}
}
/// Shadowsocks DNS resolver
///
/// A customized trust-dns-resolver
pub type DnsResolver = AsyncResolver<ShadowDnsProvider>;
/// Create a `trust-dns` asynchronous DNS resolver
pub async fn create_resolver(dns: Option<ResolverConfig>, _ipv6_first: bool) -> ResolveResult<TokioAsyncResolver> {
pub async fn create_resolver(dns: Option<ResolverConfig>, connect_opts: ConnectOpts) -> ResolveResult<DnsResolver> {
// Customized dns resolution
match dns {
Some(conf) => {
@@ -23,7 +110,7 @@ pub async fn create_resolver(dns: Option<ResolverConfig>, _ipv6_first: bool) ->
conf,
resolver_opts
);
TokioAsyncResolver::tokio(conf, resolver_opts)
DnsResolver::new(conf, resolver_opts, ShadowDnsProvider::new(connect_opts))
}
// To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration
@@ -31,7 +118,7 @@ pub async fn create_resolver(dns: Option<ResolverConfig>, _ipv6_first: bool) ->
None => {
cfg_if! {
if #[cfg(any(all(unix, not(target_os = "android")), windows))] {
use trust_dns_resolver::{name_server::TokioHandle, system_conf::read_system_conf};
use trust_dns_resolver::system_conf::read_system_conf;
// use the system resolver configuration
let (config, mut opts) = match read_system_conf() {
@@ -58,7 +145,7 @@ pub async fn create_resolver(dns: Option<ResolverConfig>, _ipv6_first: bool) ->
opts
);
TokioAsyncResolver::new(config, opts, TokioHandle)
DnsResolver::new(config, opts, ShadowDnsProvider::new(connect_opts))
} else {
use trust_dns_resolver::error::ResolveError;
@@ -226,8 +226,8 @@ pub fn set_disable_ip_fragmentation<S: AsRawFd>(af: AddrFamily, socket: &S) -> i
Ok(())
}
/// Create a `UdpSocket` for connecting to `addr`
#[inline(always)]
/// Create a `UdpSocket` with specific address family
#[inline]
pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result<UdpSocket> {
let bind_addr = match (af, config.bind_local_addr) {
(AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0),
@@ -236,11 +236,18 @@ pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) ->
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
};
bind_outbound_udp_socket(&bind_addr, config).await
}
/// Create a `UdpSocket` binded to `bind_addr`
pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, _config: &ConnectOpts) -> io::Result<UdpSocket> {
let af = AddrFamily::from(bind_addr);
let socket = if af != AddrFamily::Ipv6 {
UdpSocket::bind(bind_addr).await?
} else {
let socket = Socket::new(Domain::for_address(bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
socket_bind_dual_stack(&socket, &bind_addr, false)?;
let socket = Socket::new(Domain::for_address(*bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
socket_bind_dual_stack(&socket, bind_addr, false)?;
// UdpSocket::from_std requires socket to be non-blocked
socket.set_nonblocking(true)?;
@@ -65,7 +65,7 @@ impl TcpStream {
async fn connect_with_socket(socket: TcpSocket, addr: SocketAddr, opts: &ConnectOpts) -> io::Result<TcpStream> {
// Binds to a specific network interface (device)
if let Some(ref iface) = opts.bind_interface {
set_ip_bound_if(&socket, addr, iface)?;
set_ip_bound_if(&socket, &addr, iface)?;
}
set_common_sockopt_for_connect(addr, &socket, opts)?;
@@ -230,7 +230,7 @@ pub async fn create_inbound_tcp_socket(bind_addr: &SocketAddr, _accept_opts: &Ac
}
}
fn set_ip_bound_if<S: AsRawFd>(socket: &S, addr: SocketAddr, iface: &str) -> io::Result<()> {
fn set_ip_bound_if<S: AsRawFd>(socket: &S, addr: &SocketAddr, iface: &str) -> io::Result<()> {
const IP_BOUND_IF: libc::c_int = 25; // bsd/netinet/in.h
const IPV6_BOUND_IF: libc::c_int = 125; // bsd/netinet6/in6.h
@@ -319,7 +319,8 @@ pub fn set_disable_ip_fragmentation<S: AsRawFd>(af: AddrFamily, socket: &S) -> i
Ok(())
}
/// Create a `UdpSocket` for connecting to `addr`
/// Create a `UdpSocket` with specific address family
#[inline]
pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result<UdpSocket> {
let bind_addr = match (af, config.bind_local_addr) {
(AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0),
@@ -328,10 +329,17 @@ pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) ->
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
};
bind_outbound_udp_socket(&bind_addr, config).await
}
/// Create a `UdpSocket` binded to `bind_addr`
pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOpts) -> io::Result<UdpSocket> {
let af = AddrFamily::from(bind_addr);
let socket = if af != AddrFamily::Ipv6 {
UdpSocket::bind(bind_addr).await?
} else {
let socket = Socket::new(Domain::for_address(bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
let socket = Socket::new(Domain::for_address(*bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
socket_bind_dual_stack(&socket, &bind_addr, false)?;
// UdpSocket::from_std requires socket to be non-blocked
@@ -279,7 +279,8 @@ pub fn set_disable_ip_fragmentation<S: AsRawFd>(af: AddrFamily, socket: &S) -> i
Ok(())
}
/// Create a `UdpSocket` for connecting to `addr`
/// Create a `UdpSocket` with specific address family
#[inline]
pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result<UdpSocket> {
let bind_addr = match (af, config.bind_local_addr) {
(AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0),
@@ -288,11 +289,18 @@ pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) ->
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
};
bind_outbound_udp_socket(&bind_addr, config).await
}
/// Create a `UdpSocket` binded to `bind_addr`
pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOpts) -> io::Result<UdpSocket> {
let af = AddrFamily::from(bind_addr);
let socket = if af != AddrFamily::Ipv6 {
UdpSocket::bind(bind_addr).await?
} else {
let socket = Socket::new(Domain::for_address(bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
socket_bind_dual_stack(&socket, &bind_addr, false)?;
let socket = Socket::new(Domain::for_address(*bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
socket_bind_dual_stack(&socket, bind_addr, false)?;
// UdpSocket::from_std requires socket to be non-blocked
socket.set_nonblocking(true)?;
@@ -78,8 +78,8 @@ pub fn set_disable_ip_fragmentation<S: AsRawFd>(_af: AddrFamily, _socket: &S) ->
Ok(())
}
/// Create a `UdpSocket` for connecting to `addr`
#[inline(always)]
/// Create a `UdpSocket` with specific address family
#[inline]
pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result<UdpSocket> {
let bind_addr = match (af, config.bind_local_addr) {
(AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0),
@@ -88,6 +88,13 @@ pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) ->
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
};
bind_outbound_udp_socket(&bind_addr, config).await
}
/// Create a `UdpSocket` binded to `bind_addr`
pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, _config: &ConnectOpts) -> io::Result<UdpSocket> {
let af = AddrFamily::from(bind_addr);
let socket = UdpSocket::bind(bind_addr).await?;
let _ = set_disable_ip_fragmentation(af, &socket);
+27 -6
View File
@@ -23,8 +23,20 @@ use windows_sys::{
Foundation::BOOL,
NetworkManagement::IpHelper::if_nametoindex,
Networking::WinSock::{
setsockopt, WSAGetLastError, WSAIoctl, IPPROTO_IP, IPPROTO_IPV6, IPPROTO_TCP, IPV6_MTU_DISCOVER,
IPV6_UNICAST_IF, IP_MTU_DISCOVER, IP_PMTUDISC_DO, IP_UNICAST_IF, SIO_UDP_CONNRESET, SOCKET, SOCKET_ERROR,
setsockopt,
WSAGetLastError,
WSAIoctl,
IPPROTO_IP,
IPPROTO_IPV6,
IPPROTO_TCP,
IPV6_MTU_DISCOVER,
IPV6_UNICAST_IF,
IP_MTU_DISCOVER,
IP_PMTUDISC_DO,
IP_UNICAST_IF,
SIO_UDP_CONNRESET,
SOCKET,
SOCKET_ERROR,
TCP_FASTOPEN,
},
},
@@ -36,7 +48,9 @@ const FALSE: BOOL = 0;
use crate::net::{
is_dual_stack_addr,
sys::{set_common_sockopt_for_connect, socket_bind_dual_stack},
AcceptOpts, AddrFamily, ConnectOpts,
AcceptOpts,
AddrFamily,
ConnectOpts,
};
/// A `TcpStream` that supports TFO (TCP Fast Open)
@@ -55,7 +69,7 @@ impl TcpStream {
// Binds to a specific network interface (device)
if let Some(ref iface) = opts.bind_interface {
set_ip_unicast_if(&socket, addr, iface)?;
set_ip_unicast_if(&socket, &addr, iface)?;
}
set_common_sockopt_for_connect(addr, &socket, opts)?;
@@ -183,7 +197,7 @@ pub async fn create_inbound_tcp_socket(bind_addr: &SocketAddr, _accept_opts: &Ac
}
}
fn set_ip_unicast_if<S: AsRawSocket>(socket: &S, addr: SocketAddr, iface: &str) -> io::Result<()> {
fn set_ip_unicast_if<S: AsRawSocket>(socket: &S, addr: &SocketAddr, iface: &str) -> io::Result<()> {
let handle = socket.as_raw_socket() as SOCKET;
unsafe {
@@ -348,10 +362,17 @@ pub async fn create_outbound_udp_socket(af: AddrFamily, opts: &ConnectOpts) -> i
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
};
bind_outbound_udp_socket(&bind_addr, opts).await
}
/// Create a `UdpSocket` binded to `bind_addr`
pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, opts: &ConnectOpts) -> io::Result<UdpSocket> {
let af = AddrFamily::from(bind_addr);
let socket = if af != AddrFamily::Ipv6 {
UdpSocket::bind(bind_addr).await?
} else {
let socket = Socket::new(Domain::for_address(bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
let socket = Socket::new(Domain::for_address(*bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
socket_bind_dual_stack(&socket, &bind_addr, false)?;
// UdpSocket::from_std requires socket to be non-blocked
+11 -6
View File
@@ -35,7 +35,7 @@ use tokio::io::Interest;
use crate::{context::Context, relay::socks5::Address, ServerAddr};
use super::{
sys::{create_inbound_udp_socket, create_outbound_udp_socket},
sys::{bind_outbound_udp_socket, create_inbound_udp_socket, create_outbound_udp_socket},
AcceptOpts,
AddrFamily,
ConnectOpts,
@@ -127,6 +127,16 @@ impl UdpSocket {
Ok(UdpSocket(socket))
}
/// Binds to a specific address with opts
pub async fn connect_any_with_opts<AF: Into<AddrFamily>>(af: AF, opts: &ConnectOpts) -> io::Result<UdpSocket> {
create_outbound_udp_socket(af.into(), opts).await.map(UdpSocket)
}
/// Binds to a specific address with opts as an outbound socket
pub async fn bind_with_opts(addr: &SocketAddr, opts: &ConnectOpts) -> io::Result<UdpSocket> {
bind_outbound_udp_socket(addr, opts).await.map(UdpSocket)
}
/// Binds to a specific address (inbound)
#[inline]
pub async fn listen(addr: &SocketAddr) -> io::Result<UdpSocket> {
@@ -139,11 +149,6 @@ impl UdpSocket {
Ok(UdpSocket(socket))
}
/// Binds to a specific address with opts
pub async fn connect_any_with_opts<AF: Into<AddrFamily>>(af: AF, opts: &ConnectOpts) -> io::Result<UdpSocket> {
create_outbound_udp_socket(af.into(), opts).await.map(UdpSocket)
}
/// Batch send packets
#[cfg(any(
target_os = "linux",
+3 -3
View File
@@ -183,7 +183,7 @@ pub fn define_command_line_options(mut app: Command) -> Command {
.help("Set SIP003 plugin options"),
)
.arg(
Arg::new("URL")
Arg::new("SERVER_URL")
.long("server-url")
.num_args(1)
.action(ArgAction::Set)
@@ -192,7 +192,7 @@ pub fn define_command_line_options(mut app: Command) -> Command {
.help("Server address in SIP002 (https://shadowsocks.org/guide/sip002.html) URL"),
)
.group(ArgGroup::new("SERVER_CONFIG")
.arg("SERVER_ADDR").arg("URL").multiple(true))
.arg("SERVER_ADDR").arg("SERVER_URL").multiple(true))
.arg(
Arg::new("ACL")
.long("acl")
@@ -591,7 +591,7 @@ pub fn main(matches: &ArgMatches) -> ExitCode {
config.server.push(ServerInstanceConfig::with_server_config(sc));
}
if let Some(svr_addr) = matches.get_one::<ServerConfig>("URL").cloned() {
if let Some(svr_addr) = matches.get_one::<ServerConfig>("SERVER_URL").cloned() {
config.server.push(ServerInstanceConfig::with_server_config(svr_addr));
}