diff --git a/doc/book/src/lua/map_config.md b/doc/book/src/lua/map_config.md index f8dedb34..d738f166 100644 --- a/doc/book/src/lua/map_config.md +++ b/doc/book/src/lua/map_config.md @@ -497,7 +497,7 @@ Quic= { 须给出 server_name (域名), 且 若 is_insecure 为 false, 须为 证书中所写的 CN 或 Subject Alternative Name; -ruci 提供的 test2.crt中的 Subject +ruci 提供的 test2.crt中的 Subject Alternative Name 为 www.mytest.com 和 localhost, cert_path:可给出 服务端的 证书, 这样就算 is_insecure = false 也通过验证 diff --git a/resource/README.md b/resource/README.md index 165d6c8e..863a0e22 100644 --- a/resource/README.md +++ b/resource/README.md @@ -7,6 +7,8 @@ test.crt, test.key 用于测试用于tls的自签名证书 test.crt 为 pem 格式的 x509 证书, test.key 为 pem 格式的 EC key test2.key, test2.crt 为 自签名根证书, 比 test.crt/key 更好 +test2.crt中的 Subject Alternative Name 为 www.mytest.com 和 localhost, + inspect.lua 是一个lua模块, 来自 //https://raw.githubusercontent.com/kikito/inspect.lua/master/inspect.lua diff --git a/resource/local.lua b/resource/local.lua index 1d18f1dc..ef4d51c2 100644 --- a/resource/local.lua +++ b/resource/local.lua @@ -730,7 +730,14 @@ local function get_recorder(label) } end - +local function random_host() + local hosts = { + "www.baidu.com", + "www.bilibili.com", + -- "www.qq.com", + } + return hosts[math.random(1, #hosts)] +end local config_19_recorder_trojans = { tag_route = { { "listen_socks5", "dial_trojan" }, { "listen_trojan", "dial_direct" } }, @@ -780,7 +787,15 @@ local config_19_recorder_trojans = { } }, - tlsout, + { + NativeTLS = { + --TLS = { + host = random_host(), --"www.1234.com", + insecure = true, + alpn = { "http" } + + } + }, get_recorder("trojan"), trojan_out diff --git a/resource/local_mux_h2_recorder.lua b/resource/local_mux_h2_recorder.lua new file mode 100644 index 00000000..73f1722c --- /dev/null +++ b/resource/local_mux_h2_recorder.lua @@ -0,0 +1,115 @@ +-- 演示了 用完全动态链实现 h2 mux outbound 的配置 +-- 关注 outbounds 的 generator 部分, 它实现了单h2连接的多路复用 +local dial_config = { + BindDialer = { + dial_addr = "tcp://0.0.0.0:10801" + } +} + +local function random_host() + local hosts = { + "www.baidu.com", + "www.bilibili.com", + -- "www.qq.com", + } + return hosts[math.random(1, #hosts)] +end + +local tlsout_config = { + NativeTLS = { + --TLS = { + host = random_host(), --"www.1234.com", + insecure = true, + alpn = { "h2" } + + } +} +local trojan_out_config = { + Trojan = "mypassword" +} + +local h2_out_config = { + H2Mux = { + is_grpc = true, + http_config = { + authority = "myhost", + path = "/service1/Tun" + } + } +} + +Infinite = { + + inbounds = { { + tag = "listen1", + + generator = function(cid, state_index, data) + if state_index == -1 then + return 0, { + stream_generator = { + Listener = { listen_addr = "0.0.0.0:10800" } + }, + new_thread_fn = function(cid, state_index, data) + if Socks5_in == nil then + Socks5_in = Create_in_map { + Socks5 = {} + } + end + + local new_cid, newi, new_data = coroutine.yield(1, Socks5_in:clone()) + return -1, {} + end + } + end + end + } }, + + outbounds = { { + tag = "dial1", + generator = function(cid, state_index, data) + if state_index == -1 then + if H2_out ~= nil then + return 3, H2_out:clone() + end + + if Dial_out == nil then + Dial_out = Create_out_map(dial_config) + end + return 0, Dial_out:clone() + elseif state_index == 0 then + if Recorder == nil then + Recorder = Create_out_map({ + Recorder = { + label = "h2_trojans", + serialize_format = "cbor", + session_truncate = 2000, + } + }) + end + + return 1, Recorder:clone() + elseif state_index == 1 then + if Tlsout == nil then + Tlsout = Create_out_map(tlsout_config) + end + + return 2, Tlsout:clone() + elseif state_index == 2 then + if H2_out == nil then + H2_out = Create_out_map(h2_out_config) + end + + return 3, H2_out:clone() + elseif state_index == 3 then + if Trojan_out == nil then + Trojan_out = Create_out_map(trojan_out_config) + end + + return 4, Trojan_out:clone() + else + return -1, {} + end + end + } } + +} diff --git a/resource/remote.lua b/resource/remote.lua index 663bf667..b9f36857 100644 --- a/resource/remote.lua +++ b/resource/remote.lua @@ -34,10 +34,10 @@ local socks5http_chain = { tcp, { } } local tls = { - -- NativeTLS = { - TLS = { - cert = "test.crt", - key = "test.key", + NativeTLS = { --NativeTLS 要用 test2.crt 而不是 test.crt + --TLS = { + cert = "test2.crt", + key = "test2.key", alpn = { "h2", "http" } } @@ -126,9 +126,9 @@ local direct_out_chain = { { Direct = {} } } Config = { inbounds = { -- { chain = trojan_chain, tag = "listen1"} - { chain = trojans_chain, tag = "listen1" }, + -- { chain = trojans_chain, tag = "listen1" }, -- { chain = ws_trojans_chain, tag = "listen1" } - -- { chain = in_h2_trojans_chain, tag = "listen1" } + { chain = in_h2_trojans_chain, tag = "listen1" } -- { chain = in_quic_chain, tag = "listen1" } -- { chain = socks5http_chain, tag = "listen1"} , -- { chain = { unix,tls, trojan_in }, tag = "listen1"} , diff --git a/rucimp/examples/readme.md b/rucimp/examples/readme.md index f87968dc..72f2fd15 100644 --- a/rucimp/examples/readme.md +++ b/rucimp/examples/readme.md @@ -4,11 +4,13 @@ rucimp 的 examples 提供数个示例可执行文件,主要目的是提供演 (若要全功能, See [ruci-cmd](crates/ruci-cmd/README.md)) -suit, chain 分为以不同的代码运行 suit模式和 chain 模式, -还有 chain_trace 演示 单连接流量监控 +chain_trace 演示 单连接流量监控 chain_infinite 演示 完全动态链, 其与 chain 的运行方式一样, 不再赘述 +run_h2_trojans_recorder_pair.sh 同时运行h2 的 local 和 remote端用于测试并生成 recorder记录文件 + + # 通用 接受 一个 命令行参数, 将其作为配置文件读取, 未提供或者找不到时, 会在工作目录, ruci_config/ , resource/ , ../resource 等 目录下找默认的配置文件. @@ -25,9 +27,6 @@ RUST_LOG=none,ruci=debug cargo run --features "lua quinn tun" --example chain_in # linux RUST_LOG=none,ruci=debug cargo run --features "lua quinn tun sockopt" --example chain -# suit mode -cargo run --example suit -- local.suit.toml -cargo run --example suit -- remote.suit.toml ``` ( (h2 的代码实现所依赖的 h2包)、 quic 包、 rustls 等包 都会在debug 下打印大量日志输出, 影响观察ruci本身的日志信息, @@ -76,10 +75,3 @@ ping 10.0.0.2 自动路由的配置示例见 [resource/local.lua](../../resource/local.lua) 和 [resource/remote.lua](../../resource/remote.lua) (在文件中搜索 auto_route ) - -# suit 的功能还不全 - -目前 ruci 项目处于开发阶段, 关注点主要在 chain 模式上面. suit 模式目前只有tcp , - 没有 udp 和 unix domain socket, 也没有路由 -(suit 模式是仿照verysimple的架构的模式, ruci 目前有此 suit 模式 的意图主要是为了指出,ruci 的新的设计可以 -导出 很多其它架构,即ruci 的设计是更一般的设计) diff --git a/rucimp/examples/run_h2_trojans_recorder_pair.sh b/rucimp/examples/run_h2_trojans_recorder_pair.sh new file mode 100644 index 00000000..5a787bdd --- /dev/null +++ b/rucimp/examples/run_h2_trojans_recorder_pair.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +RUST_LOG=none,ruci=debug cargo run --features "lua quinn tun smoltcp use-native-tls" --example chain -- remote.lua & +PID1=$! + +RUST_LOG=none,ruci=debug cargo run --features "lua quinn tun smoltcp use-native-tls" --example chain_infinite -- local_mux_h2_recorder.lua & +PID2=$! + +sleep 5 + +kill $PID1 + +sleep 1 + +kill $PID2 + diff --git a/rucimp/src/map/recorder.rs b/rucimp/src/map/recorder.rs index 2364a3d2..f7c6778c 100644 --- a/rucimp/src/map/recorder.rs +++ b/rucimp/src/map/recorder.rs @@ -317,9 +317,24 @@ impl AsyncRead for RecorderConn { buf: &mut tokio::io::ReadBuf<'_>, ) -> Poll> { let r = self.base.as_mut().poll_read(cx, buf); + if let Poll::Ready(r) = &r { match r { - Ok(_) => self.record.record_d(buf.filled()), + Ok(_) => { + let l = buf.filled().len(); + + //tcp EOF 的情况 + if l == 0 { + info!( + cid = %self.record.data.cid, + "recorder read got EOF(len=0), Saving to file", + ); + + self.record.data.save(); + } else { + self.record.record_d(buf.filled()) + } + } Err(e) => { info!( cid = %self.record.data.cid,