skcptun
skcptun is encrypted KCP tunnel for OpenWRT and Linux and MacOS, implemented in C language and Lua.
狀態
- “又不是不能用”
- 目前是加入了Lua的版本,純C版本不再維護了。
特性
- 基於可靠UDP的加密隧道,加密後的傳輸資料沒有任何特徵。
- 可用於加速網路連接,有急速模式和普通模式,實測急速模式的傳輸速度遠大於TCP傳輸。 (bench mark)
- 目前支援兩種模式:TUN模式和TCP模式
- TUN模式,客戶端和服務端各建立一個同一網段的虛擬網卡,客戶端將所有IP包透過加密的KCP隧道透傳到服務端,類似傳統的VPN模式
- TCP模式,客戶端監聽一個(或多個)端口,將接收到的所有資料透過加密的KCP隧道透傳到服務端,服務端將資料透傳給指定的伺服器,一般在TUN模式受阻時使用
- 可以基於skcptun提供的API用Lua腳本實現自己客製化的服務
安裝
運作環境:Linux,MacOS
依賴函式庫:OpenSSL,libev
下載原始碼並解壓縮後:
cd skcptun
mkdir build
cd build
cmake ..
make
如果是直接clone,需要更新子模組:
git submodule update --init --recursive
環境配置
TCP模式
TUN模式
- 由於是透過虛擬網路卡的技術建立的隧道,需要做必要的網路設定。
- 以linux(debian)為例,需要核心支援tun模組。透過“modinfo tun”命令確認。
- 需要安裝"iproute2" 和“iptables” 工具包。
服務端
- 開啟ip轉發,將下列設定新增至"/etc/sysctl.conf" 文件,執行「sysctl -p」生效。
net.ipv4.ip_forward=1
net.ipv4.conf.all.route_localnet = 1
net.ipv4.conf.default.route_localnet = 1
net.ipv4.conf.[网卡接口].route_localnet = 1
net.ipv4.conf.lo.route_localnet = 1
net.ipv4.conf.[虚拟网卡接口].route_localnet = 1
- 開啟ip轉發,修改預設轉送策略“iptables -P FORWARD ACCEPT”
- 修改nat的來源位址改成出口網路卡的位址“iptables -t nat -A POSTROUTING -s 192.168.2.1/24 -o enp1s0 -j MASQUERADE”
客戶端
使用
- configfile是設定檔
- 如果是TUN模式需要root權限運行
設定檔:
設定檔為Lua文件,參考“skcptun_config_sample”,內有註解。
skcptun 提供的內部變數
skt
“skt”是一個供Lua腳本使用的內建全域變量,包含了“skt.conf.* ”, “skt.api.* ”,“skt.cb.* ”三部分。
skcptun的設定訊息
“skt.conf.*”:skcptun向Lua腳本暴露的配置資訊變數。
skt.conf.tun_ip
虛擬網卡的ip,客戶端和服務端需要設定為相同網段,「tun_client」和「tun_server」模式中有效。
skt.conf.tun_mask
虛擬網路卡的子網路遮罩,客戶端和服務端設定保持一致,在「tun_client」和「tun_server」模式中有效。
skt.conf.skcp_serv_conf_list_size
“skcp_serv_conf”的個數。
skt.conf.skcp_serv_conf_list[i].raw
第i個「skcp_serv_conf」本身指針,用來給API傳參。
skt.conf.skcp_serv_conf_list[i].addr
第i個「skcp_serv_conf」的IP位址
skt.conf.skcp_serv_conf_list[i].port
第i個「skcp_serv_conf」的端口
skt.conf.skcp_serv_conf_list[i].key
第i個「skcp_serv_conf」的加密串
skt.conf.skcp_serv_conf_list[i].ticket
第i個「skcp_serv_conf」的客戶端和服務端約定的存取票據,「tun_client」和「proxy_client」模式中有效。
skt.conf.skcp_serv_conf_list[i].max_conn_cnt
第i個「skcp_serv_conf」的最大連線數,「proxy_server」和「tun_server」模式中有效。
skt.conf.skcp_cli_conf_list* 設定同skt.conf.skcp_serv_conf_list*
skt.conf.etcp_serv_conf_list_size
"etcp_serv_conf_list"的個數
skt.conf.etcp_serv_conf_list[i].raw
tcp服務端「etcp_serv_conf」本身的指針,用來傳參給API。
skt.conf.etcp_serv_conf_list[i].addr
tcp服務端的監聽位址。
skt.conf.etcp_serv_conf_list[i].port
tcp服務端的監聽埠。
skt.conf.etcp_cli_conf_list_size
"etcp_cli_conf_list"的個數
skt.conf.etcp_cli_conf_list[i].raw
tcp客戶端「etcp_cli_conf」本身的指針,用於給API傳參。
skt.conf.etcp_cli_conf_list[i].addr
tcp客戶端的連線位址,在「proxy server」模式下有效。
skt.conf.etcp_cli_conf_list[i].port
tcp客戶端的連接端口,在“proxy server”模式下有效。
skcptun 提供的內部Lua API
“skt.api.*”,skcptun向Lua腳本揭露的API。
skt.api.skcp_init(conf, loop, skcp_mode)
初始化skcp。
- 參數
- conf:skcp的配置
- loop:事件循環對象
- skcp_mode:skcp的啟動模式,整型,1表示服務端模式,2表示客戶端模式
- 傳回值
- 失敗返回"nil, error_msg"
- 成功回傳skcp對象
skt.api.skcp_free(skcp)
銷毀釋放skcp。
skt.api.skcp_req_cid(skcp, ticket)
向skcp服務端請求connection id。
- 參數
- skcp對象
- ticket:配置資訊中對應的票據,字串
- 傳回值
- 失敗返回"nil, error_msg"
- 成功返回“ok”
skt.api.skcp_send(skcp, cid, buf)
透過skcp發送訊息。
- 參數
- skcp對象
- cid:skcp的connection id,整數
- buf:訊息內容,字串
- 傳回值
- 失敗返回"nil, error_msg"
- 成功返回成功發送的位元組數>=0,整數
skt.api.skcp_close_conn(skcp, cid)
關閉一個skcp的連線。
- 參數
- skcp對象
- cid:skcp的connection id,整數
- 傳回值
- 失敗返回"nil, error_msg"
- 成功返回0,整型
skt.api.skcp_get_conn(skcp, cid)
取得一個skcp的連線。
- 參數
- skcp對象
- cid:skcp的connection id,整數
- 傳回值
- 失敗返回"nil, error_msg"
- 成功conn對象
skt.api.etcp_server_init(conf, loop)
初始化etcp服務端。
- 參數
- 傳回值
- 失敗返回"nil, error_msg"
- 成功返回etcp服務端對象
skt.api.etcp_server_free(etcp)
銷毀和釋放etcp服務端。
skt.api.etcp_server_send(etcp, fd, buf)
透過etcp向客戶端發送訊息。
- 參數
- etcp服務端對象
- fd:對應的fd,整數型
- buf:訊息內容,字串
- 傳回值
- 失敗返回"nil, error_msg"
- 成功返回成功發送的位元組數>0,整數
skt.api.etcp_server_get_conn(etcp, fd)
取得一個etcp服務端的連線。
- 參數
- 傳回值
- 失敗返回"nil, error_msg"
- 成功返回conn對象
skt.api.etcp_server_close_conn(etcp, fd, silent)
關閉一個etcp服務端的連線。
- 參數
- etcp服務端對象
- fd:對應的fd,整數型
- silent:是否靜默關閉,如果不是靜默關閉則觸發「on_close」事件,1表示靜默關閉,0表示非靜默關閉。
- 傳回值:無
skt.api.etcp_client_init(conf, loop)
初始化etcp客戶端。
- 參數
- 傳回值
- 失敗返回"nil, error_msg"
- 成功返回etcp客戶端對象
skt.api.etcp_client_free(etcp)
銷毀和釋放etcp客戶端。
skt.api.etcp_client_send(etcp, fd, buf)
透過etcp向服務端發送訊息。
- 參數
- etcp客戶端對象
- fd:對應的fd,整數型
- buf:訊息內容,字串
- 傳回值
- 失敗返回"nil, error_msg"
- 成功返回成功發送的位元組數>0,整數
skt.api.etcp_client_create_conn(etcp, addr, port)
建立一個etcp連線。
- 參數
- etcp客戶端對象
- addr:需要連接服務端位址,字串
- port:需要連接服務端端口
- 傳回值
- 失敗返回"nil, error_msg"
- 成功返回已建立的fd,整型
skt.api.etcp_client_close_conn(etcp, fd)
關閉一個etcp客戶端的連線。
skt.api.etcp_client_get_conn(etcp, fd)
獲得一個etcp客戶端的連線。
- 參數
- 傳回值
- 失敗返回"nil, error_msg"
- 成功返回conn對象
skt.api.tuntap_write(fd, buf)
往虛擬網路卡寫入資料。
- 參數
- fd:虛擬網路卡的fd,整型
- buf:需要寫入的數據,字串
- 傳回值
- 失敗返回"nil, error_msg"
- 成功寫入的位元組數,整數
skt.api.get_from_skcp(skcp, name)
取得skcp物件中對應欄位值,即:「skcp.name」。
- 參數
- skcp對象
- name:skcp中的字段名,目前只支援「fd」一個字段,字串
- 傳回值
- 失敗返回"nil, error_msg"
- 成功傳回name對應的值,any
skt.api.get_ms()
取得目前系統自1970年以來的毫秒數。
skt.api.hton32(i)
將32位元的整數變數從主機位元組序轉變成網路字節序。
skt.api.ntoh32(i)
將32位元的整數變數從網路位元組序轉變成主機位元組序。
skt.api.band(a, b)
將兩個整數位元做邏輯與操作,並返回結果
skt.api.bor(a, b)
將兩個整數位元做邏輯或操作,傳回結果
skt.api.bxor(a, b)
將兩個整數位元做異或操作,傳回結果
skt.api.blshift(i, n)
將整數位左移n位,回傳結果
skt.api.brshift(i, n)
將整數按位右移n位,並返回結果
skt.api.lookup_dns(domain)
網域解析
Lua腳本需要實現的回呼接口
“skt.cb.*”,根據不同的啟動模式需要實現不一樣的接口,以供skcptun回調。
skt.cb.on_init(loop)
腳本啟動時第一個呼叫的回呼接口,且只呼叫一次
skt.cb.on_skcp_accept(skcp, cid)
skcp服務端成功建立一個cid,每個connection只呼叫一次。
- 有效範圍:“proxy_server”,“tun_server”
- 參數
- skcp對象
- cid:skcp的connection id,整數
- 傳回值:無
skt.cb.on_skcp_check_ticket(skcp, ticket)
skcp服務端校驗ticket是否正確。
- 有效範圍:“proxy_server”,“tun_server”
- 參數
- 傳回值:
skt.cb.on_skcp_recv_cid(skcp, cid)
skcp收到一個cid,表示成功和skcp服務端建立了一個連線。即「skt.api.skcp_req_cid(skcp, ticket)」的非同步結構回傳。
- 有效範圍:“proxy_client”,“tun_client”
- 參數
- skcp對象
- cid:skcp的connection id,整數
- 傳回值:無
skt.cb.on_skcp_recv_data(skcp, cid, buf)
skcp收到cid對應連線的資料。
- 有效範圍:所有模式
- 參數
- skcp對象
- cid:skcp的connection id,整數
- buf:收到的訊息內容,字串
- 傳回值:無
skt.cb.on_skcp_close(skcp, cid)
skcp關閉一個連線時的回調,一般可能是逾時造成的或是收到對端的close指令,此刻連線還未真正關閉。
- 有效範圍:所有模式
- 參數
- skcp對象
- cid:skcp的connection id,整數
- 傳回值:無
skt.cb.on_tcp_accept(fd)
tcp服務端收到一個連線請求。
- 有效範圍:“proxy_client”,“tun_client”
- 參數
- 傳回值:無
skt.cb.on_tcp_recv(fd, buf)
收到fd對應連線的tcp資料。
- 有效範圍:所有模式
- 參數
- fd:該連接的fd,整數
- buf:收到的訊息內容,字串
- 傳回值:無
skt.cb.on_tcp_close(fd)
關閉fd對應的tcp連接,此刻連接還未真正關閉。
skt.cb.on_tun_read(buf)
收到來自虛擬網路卡的資料。
- 有效範圍:“tun_client”,“tun_server”
- 參數
- 傳回值:無
skt.cb.on_beat()
每一秒觸發一次調用。
- 有效範圍:“proxy_client”,“tun_client”
- 參數:無
- 傳回值:無
測試
環境
- 伺服器:Linux/1C/1G
- 客戶端:MacOS/8C/8G
- 網路狀況,ping值:
21 packets transmitted, 20 packets received, 4.8% packet loss
round-trip min/avg/max/stddev = 159.492/164.087/171.097/3.232 ms
過程資料(RTT)
- 連線數:1;資料包:1000;發送間隔:100ms
TCP RTT:
------------
Min = 161.0
Max = 1239.0
Average = 293.956
NR = 1000
Skcptun RTT:
------------
Min = 160.0
Max = 487.0
Average = 181.618
NR = 1000
- 連線數:10;資料包:1000;發送間隔:100ms
TCP RTT:
------------
Min = 159.0
Max = 1076.0
Average = 262.500
NR = 10000
Skcptun RTT:
------------
Min = 159.0
Max = 534.0
Average = 174.251
NR = 10000
結論
注意
- 剛寫完,自用且功能完善中
- 請務必不要用於加速加密sock5代理程式哦?