diff --git a/Cargo.lock b/Cargo.lock index 6011758..f32668b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,15 +11,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anyhow" version = "1.0.52" @@ -49,27 +40,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "boomphf" version = "0.5.9" @@ -82,17 +58,6 @@ dependencies = [ "wyhash", ] -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", -] - [[package]] name = "byteorder" version = "1.4.3" @@ -117,21 +82,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim 0.8.0", - "textwrap 0.11.0", - "unicode-width", - "vec_map", -] - [[package]] name = "clap" version = "3.0.14" @@ -144,9 +94,9 @@ dependencies = [ "indexmap", "lazy_static", "os_str_bytes", - "strsim 0.10.0", + "strsim", "termcolor", - "textwrap 0.14.2", + "textwrap", ] [[package]] @@ -155,7 +105,7 @@ version = "3.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a1132dc3944b31c20dd8b906b3a9f0a5d0243e092d59171414969657ac6aa85" dependencies = [ - "heck 0.4.0", + "heck", "proc-macro-error", "proc-macro2", "quote", @@ -178,15 +128,6 @@ dependencies = [ "yaml-rust", ] -[[package]] -name = "cpufeatures" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" -dependencies = [ - "libc", -] - [[package]] name = "crossbeam-channel" version = "0.5.2" @@ -231,74 +172,12 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "dhcp4r" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afabc97435078b9a514bbdd13726797a7e47ae31a0c09ded1bbf74bc9232bb38" -dependencies = [ - "enum-primitive-derive", - "nom 7.1.0", - "num-traits 0.2.14", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dns-parser" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" -dependencies = [ - "byteorder", - "quick-error", -] - [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" -[[package]] -name = "enum-primitive-derive" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c375b9c5eadb68d0a6efee2999fef292f45854c3444c86f09d8ab086ba942b0e" -dependencies = [ - "num-traits 0.2.14", - "quote", - "syn", -] - [[package]] name = "enum_primitive" version = "0.1.1" @@ -308,19 +187,6 @@ dependencies = [ "num-traits 0.1.43", ] -[[package]] -name = "env_logger" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - [[package]] name = "fast-socks5" version = "0.6.1" @@ -442,16 +308,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getrandom" version = "0.2.3" @@ -469,15 +325,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "heck" version = "0.4.0" @@ -493,12 +340,6 @@ dependencies = [ "libc", ] -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "idna" version = "0.2.3" @@ -857,12 +698,6 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - [[package]] name = "os_str_bytes" version = "6.0.0" @@ -901,17 +736,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" -[[package]] -name = "pcap-sys" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "114725dfe222c031086765fc138cf20291840ee1290883bcfacaca5f226289a3" -dependencies = [ - "libc", - "pkg-config", - "winapi", -] - [[package]] name = "percent-encoding" version = "2.1.0" @@ -968,22 +792,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" - -[[package]] -name = "pktparse" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8aeb7ec35e7fdd2ecd56d39d56f843197f243d08cc4d51cf6b37268393d5e1b" -dependencies = [ - "nom 7.1.0", - "serde 1.0.133", -] - [[package]] name = "ppv-lite86" version = "0.2.16" @@ -1110,12 +918,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quote" version = "1.0.14" @@ -1199,22 +1001,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "redox_users" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" -dependencies = [ - "getrandom", - "redox_syscall", -] - -[[package]] -name = "reduce" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d2dc47b68ac15ea328cd7ebe01d7d512ed29787f7d534ad2a3c341328b35d7" - [[package]] name = "regex" version = "1.5.4" @@ -1226,12 +1012,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - [[package]] name = "regex-syntax" version = "0.6.25" @@ -1253,7 +1033,7 @@ version = "0.2.0" dependencies = [ "anyhow", "boomphf", - "clap 3.0.14", + "clap", "config", "fast-socks5", "futures", @@ -1264,14 +1044,14 @@ dependencies = [ "lazy_static", "maxminddb", "nix 0.23.1", - "pktparse", + "nom 7.1.0", "protobuf", "protoc-bin-vendored", "protoc-rust", "rtnetlink", "serde 1.0.133", - "sniffglue", "thiserror", + "tls-parser", "tokio", "tuple", "url", @@ -1325,15 +1105,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "seccomp-sys" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bcf74ba0708aeaf8d702e4f84f7458ae1de42d80e2c20963a395b6038e6be6" -dependencies = [ - "libc", -] - [[package]] name = "serde" version = "0.8.23" @@ -1383,19 +1154,6 @@ dependencies = [ "serde 1.0.133", ] -[[package]] -name = "sha2" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" -dependencies = [ - "block-buffer", - "cfg-if", - "cpufeatures", - "digest", - "opaque-debug", -] - [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -1423,40 +1181,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" -[[package]] -name = "sniffglue" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f056bfa09e8fae5f4cc0e1d4e8ae3619050644b321800d0d6a8cc778eb80aaf3" -dependencies = [ - "ansi_term", - "anyhow", - "atty", - "base64", - "bstr", - "dhcp4r", - "dirs-next", - "dns-parser", - "env_logger", - "libc", - "log", - "nix 0.23.1", - "nom 7.1.0", - "num_cpus", - "pcap-sys", - "pktparse", - "reduce", - "serde 1.0.133", - "serde_derive", - "serde_json", - "sha2", - "structopt", - "syscallz", - "tls-parser", - "toml", - "users", -] - [[package]] name = "socket2" version = "0.4.4" @@ -1473,60 +1197,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "structopt" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" -dependencies = [ - "clap 2.34.0", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck 0.3.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "strum" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2" - -[[package]] -name = "strum_macros" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec" -dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "syn" version = "1.0.84" @@ -1538,19 +1214,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "syscallz" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d94a506596d31342f15e130c31b7356b12bd1e74d316af44ff8a2d47011f9a17" -dependencies = [ - "log", - "pkg-config", - "seccomp-sys", - "strum", - "strum_macros", -] - [[package]] name = "tempfile" version = "3.3.0" @@ -1574,15 +1237,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "textwrap" version = "0.14.2" @@ -1699,12 +1353,6 @@ dependencies = [ "serde 1.0.133", ] -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - [[package]] name = "unicode-bidi" version = "0.3.7" @@ -1720,18 +1368,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - [[package]] name = "unicode-xid" version = "0.2.2" @@ -1750,22 +1386,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "users" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" -dependencies = [ - "libc", - "log", -] - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index dd863c5..a450283 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,8 +9,6 @@ edition = "2021" tokio = { version = "1", features = ["full"] } nix = "0.23.1" futures = "0.3.19" -sniffglue = "0.14.0" -pktparse = { version = "0.7", features = [] } config = "0.11" serde = "1" iprange = "0.6.6" @@ -26,6 +24,8 @@ clap = { version = "3.0.14", features = ["derive"] } anyhow = "1.0" thiserror = "1.0" protobuf = "2.27.1" +nom = "7" +tls-parser = "0.11.0" [target.'cfg(target_os = "linux")'.dependencies] iptables = "*" @@ -33,4 +33,4 @@ rtnetlink = "0.9.0" [build-dependencies] protoc-rust = "2" -protoc-bin-vendored = "3.0.0" \ No newline at end of file +protoc-bin-vendored = "3.0.0" diff --git a/src/main.rs b/src/main.rs index 65522ed..c1ab30f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod rules; mod protos; +mod sniffer; mod settings; mod socks5; diff --git a/src/sniffer/http_parse.rs b/src/sniffer/http_parse.rs new file mode 100644 index 0000000..0ffb940 --- /dev/null +++ b/src/sniffer/http_parse.rs @@ -0,0 +1,176 @@ +// NOTE: vendored from here until this is uploaded to crates.io: +// https://github.com/Geal/nom_benchmarks/blob/master/http/nom-http/src/main.rs +// All credits belong to @Geal + +use nom::branch::alt; +use nom::bytes::complete::{tag, take_while1}; +use nom::character::complete::char; +use nom::multi::many1; +use nom::sequence::{delimited, pair, preceded, terminated}; +use nom::IResult; + +#[derive(Debug, PartialEq, Clone, Copy)] +pub struct Request<'a> { + pub method: &'a [u8], + pub uri: &'a [u8], + pub version: &'a [u8], +} + +#[derive(Debug, PartialEq)] +pub struct Header<'a> { + pub name: &'a [u8], + pub value: Vec<&'a [u8]>, +} + +fn is_token(c: u8) -> bool { + !matches!(c, + 128..=255 | + 0..=31 | + b'(' | + b')' | + b'<' | + b'>' | + b'@' | + b',' | + b';' | + b':' | + b'\\' | + b'"' | + b'/' | + b'[' | + b']' | + b'?' | + b'=' | + b'{' | + b'}' | + b' ' + ) +} + +fn not_line_ending(c: u8) -> bool { + c != b'\r' && c != b'\n' +} + +fn is_space(c: u8) -> bool { + c == b' ' +} + +fn is_not_space(c: u8) -> bool { + c != b' ' +} +fn is_horizontal_space(c: u8) -> bool { + c == b' ' || c == b'\t' +} + +fn is_version(c: u8) -> bool { + (b'0'..=b'9').contains(&c) || c == b'.' +} + +fn line_ending(input: &[u8]) -> IResult<&[u8], &[u8]> { + alt((tag(b"\r\n"), tag(b"\n")))(input) +} + +fn request_line(input: &[u8]) -> IResult<&[u8], Request> { + let (input, method) = take_while1(is_token)(input)?; + let (input, _) = take_while1(is_space)(input)?; + let (input, uri) = take_while1(is_not_space)(input)?; + let (input, _) = take_while1(is_space)(input)?; + let (input, version) = http_version(input)?; + let (input, _) = line_ending(input)?; + + Ok(( + input, + Request { + method, + uri, + version, + }, + )) +} + +fn http_version(input: &[u8]) -> IResult<&[u8], &[u8]> { + preceded(tag(b"HTTP/"), take_while1(is_version))(input) +} + +fn message_header_value(input: &[u8]) -> IResult<&[u8], &[u8]> { + delimited( + take_while1(is_horizontal_space), + take_while1(not_line_ending), + line_ending, + )(input) +} + +fn message_header(input: &[u8]) -> IResult<&[u8], Header> { + let (input, name) = take_while1(is_token)(input)?; + let (input, _) = char(':')(input)?; + let (input, value) = many1(message_header_value)(input)?; + + Ok((input, Header { name, value })) +} + +pub fn request(input: &[u8]) -> IResult<&[u8], (Request, Vec
)> { + terminated(pair(request_line, many1(message_header)), line_ending)(input) +} + +pub fn parse_host(remaining: &[u8]) -> Option { + if let Ok((_remaining, (_request, headers))) = request(remaining) { + for header in headers { + if let Ok(name) = std::str::from_utf8(header.name) { + match name.to_lowercase().as_str() { + "host" => { + return String::from_utf8( + header + .value + .into_iter() + .flat_map(ToOwned::to_owned) + .collect(), + ) + .map(|d| d.split(":").next().unwrap().to_owned()) + .ok(); + } + _ => (), + } + } + } + } + None +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn asdf() { + let (_, (req, headers)) = request( + b"GET / HTTP/1.1 +Host: example.com +User-Agent: just/testing + +", + ) + .unwrap(); + + assert_eq!( + req, + Request { + method: b"GET", + uri: b"/", + version: b"1.1", + } + ); + assert_eq!( + headers, + &[ + Header { + name: b"Host", + value: vec![b"example.com"], + }, + Header { + name: b"User-Agent", + value: vec![b"just/testing"], + }, + ] + ); + } +} diff --git a/src/sniffer/mod.rs b/src/sniffer/mod.rs new file mode 100644 index 0000000..e4abf64 --- /dev/null +++ b/src/sniffer/mod.rs @@ -0,0 +1,13 @@ +mod http_parse; +mod tls_parse; + +pub fn parse_host(remaining: &[u8]) -> Option { + if let Some(host) = http_parse::parse_host(remaining) { + return Some(host); + } + + if let Some(host) = tls_parse::parse_host(remaining) { + return Some(host); + } + None +} diff --git a/src/sniffer/tls_parse.rs b/src/sniffer/tls_parse.rs new file mode 100644 index 0000000..ae85c0a --- /dev/null +++ b/src/sniffer/tls_parse.rs @@ -0,0 +1,25 @@ +use tls_parser::{parse_tls_extension, TlsExtension, TlsMessage, TlsMessageHandshake}; + +pub fn parse_host(remaining: &[u8]) -> Option { + if let Ok((_remaining, tls)) = tls_parser::parse_tls_plaintext(remaining) { + for msg in tls.msg { + match msg { + TlsMessage::Handshake(TlsMessageHandshake::ClientHello(ch)) => { + if let Some(mut remaining) = ch.ext { + while let Ok((remaining2, ext)) = parse_tls_extension(remaining) { + remaining = remaining2; + if let TlsExtension::SNI(sni) = ext { + for s in sni { + return std::str::from_utf8(s.1).ok().map(|s| s.to_string()); + } + } + } + } + } + _ => {} + } + } + } + + return None; +} diff --git a/src/tproxy/tproxy_linux.rs b/src/tproxy/tproxy_linux.rs index 15c9161..d8d94ec 100644 --- a/src/tproxy/tproxy_linux.rs +++ b/src/tproxy/tproxy_linux.rs @@ -100,39 +100,14 @@ pub async fn handle_intercept_sock(sock: &tokio::net::TcpSocket) -> tokio::io::R } async fn handle_tcp(inbound: &mut tokio::net::TcpStream) -> Result<()> { - use pktparse::tcp::TcpHeader; - use sniffglue::centrifuge::tcp::extract as tcp_extract; - use sniffglue::structs::tcp::TCP as TCP_CATEGORY; - use sniffglue::structs::tls::TLS; - use crate::rules::{InboundProtocol, RouteContext, TargetAddr}; use crate::utils::{is_valid_domain, transfer_tcp}; let mut buffer = [0u8; 0x400]; - let dummy_tcp_header = TcpHeader::default(); inbound.peek(&mut buffer).await?; - let __now = std::time::Instant::now(); - let cate = match tcp_extract(&dummy_tcp_header, &buffer) { - Ok(c) => c, - Err(_) => TCP_CATEGORY::Empty, - }; - let __elapsed_time = __now.elapsed(); - - let domain = match cate { - TCP_CATEGORY::HTTP(http_req) => http_req.host, - TCP_CATEGORY::TLS(tls_hello) => match tls_hello { - TLS::ClientHello(client_hello) => { - if is_valid_domain(client_hello.hostname.as_deref().unwrap_or_default()) { - client_hello.hostname - } else { - None - } - } - _ => None, - }, - _ => None, - }; + let domain = crate::sniffer::parse_host(&buffer) + .filter(|s| is_valid_domain(s.as_str())); let target_addr = match domain { Some(domain) => TargetAddr::Domain(