skcptun
skcptun は、OpenWRT、Linux、MacOS 用の暗号化された KCP トンネルで、C 言語と Lua で実装されています。
州
- 「使えないわけではない」
- 現在はLuaを追加したバージョンとなっており、純粋なCバージョンはメンテナンスされなくなっています。
特性
- 信頼性の高い UDP 暗号化トンネルに基づいており、暗号化された送信データには特徴がありません。
- 高速モードと通常モードを使用して、ネットワーク接続を高速化するために使用できます。高速モードの測定された伝送速度は、TCP 伝送よりもはるかに高速です。 (ベンチマーク)
- 現在、TUN モードと TCP モードの 2 つのモードをサポートしています。
- TUN モードでは、クライアントとサーバーはそれぞれ、同じネットワーク セグメント上に仮想ネットワーク カードを作成します。クライアントは、従来の VPN モードと同様に、暗号化された KCP トンネルを通じてすべての IP パケットをサーバーに透過的に送信します。
- TCP モードでは、クライアントは 1 つ (または複数) のポートをリッスンし、暗号化された KCP トンネルを介してすべての受信データをサーバーに透過的に送信します。これは通常、TUN モードがブロックされている場合に使用されます。
- Lua スクリプトを使用して、skcptun が提供する API に基づいて独自にカスタマイズしたサービスを実装できます。
インストール
動作環境:Linux、MacOS
依存ライブラリ: OpenSSL、libev
ソース コードをダウンロードして解凍した後、次のようにします。
cd skcptun
mkdir build
cd build
cmake ..
make
直接クローンを作成する場合は、サブモジュールを更新する必要があります。
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」は、「skt.conf.*」、「skt.api.*」、「skt.cb.*」などの Lua スクリプトで使用される組み込みグローバル変数です。
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 クライアントの接続アドレス。「プロキシ サーバー」モードで有効です。
skt.conf.etcp_cli_conf_list[i].port
TCP クライアントの接続ポート。「プロキシ サーバー」モードで有効です。
skcptun によって提供される内部 Lua API
「skt.api.*」、skcptun によって Lua スクリプトに公開される API。
skt.api.skcp_init(conf, ループ, skcp_mode)
skcpを初期化します。
- パラメータ
- conf: skcpの設定
- ループ: イベントループオブジェクト
- skcp_mode: skcp 起動モード、整数、1 はサーバー モードを表し、2 はクライアント モードを表します
- 戻り値
- 失敗すると「nil、error_msg」が返されます
- skcp オブジェクトが正常に返されました。
skt.api.skcp_free(skcp)
skcpを破棄して解放します。
skt.api.skcp_req_cid(skcp, チケット)
skcp サーバーに接続 ID を要求します。
- パラメータ
- skcpオブジェクト
- ticket: 設定情報内の対応するチケット、文字列
- 戻り値
- 失敗すると「nil、error_msg」が返されます
- 正常に「ok」を返します
skt.api.skcp_send(skcp、cid、buf)
skcp 経由でメッセージを送信します。
- パラメータ
- skcpオブジェクト
- cid: skcp の接続 ID、整数
- buf: メッセージの内容、文字列
- 戻り値
- 失敗すると「nil、error_msg」が返されます
- 正常に送信されたバイト数 >= 0 (整数) を返します。
skt.api.skcp_close_conn(skcp, cid)
skcp接続を閉じます。
- パラメータ
- skcpオブジェクト
- cid: skcp の接続 ID、整数
- 戻り値
- 失敗すると「nil、error_msg」が返されます
- 正常に整数の 0 を返します
skt.api.skcp_get_conn(skcp, cid)
skcp接続を取得します。
- パラメータ
- skcpオブジェクト
- cid: skcp の接続 ID、整数
- 戻り値
- 失敗すると「nil、error_msg」が返されます
- 成功コンオブジェクト
skt.api.etcp_server_init(conf, ループ)
etcpサーバーを初期化します。
- パラメータ
- conf: skcpの設定
- ループ: イベントループオブジェクト
- 戻り値
- 失敗すると「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 サーバーへの接続を取得します。
- パラメータ
- etcpサーバーオブジェクト
- fd: 対応する fd、整数
- 戻り値
- 失敗すると「nil、error_msg」が返されます
- conn オブジェクトが正常に返されます。
skt.api.etcp_server_close_conn(etcp、fd、サイレント)
etcp サーバー接続を閉じます。
- パラメータ
- etcpサーバーオブジェクト
- fd: 対応する fd、整数
- Silent: サイレントに閉じない場合、「on_close」イベントがトリガーされます。1 はサイレントに閉じ、0 はサイレントに閉じられません。
- 戻り値: なし
skt.api.etcp_client_init(conf, ループ)
etcpクライアントを初期化します。
- パラメータ
- conf: skcpの設定
- ループ: イベントループオブジェクト
- 戻り値
- 失敗すると「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、アドレス、ポート)
etcp接続を作成します。
- パラメータ
- etcpクライアントオブジェクト
- addr: サーバーアドレス、文字列に接続する必要があります
- port: サーバーポートに接続する必要があります
- 戻り値
- 失敗すると「nil、error_msg」が返されます
- 作成した fd を整数型で返すことに成功しました。
skt.api.etcp_client_close_conn(etcp, fd)
etcp クライアント接続を閉じます。
- パラメータ
- etcpクライアントオブジェクト
- fd: 対応する fd、整数
- 戻り値: なし
skt.api.etcp_client_get_conn(etcp, fd)
etcp クライアント接続を取得します。
- パラメータ
- etcpクライアントオブジェクト
- fd: 対応する fd、整数
- 戻り値
- 失敗すると「nil、error_msg」が返されます
- conn オブジェクトが正常に返されます。
skt.api.tuntap_write(fd, buf)
仮想ネットワーク カードにデータを書き込みます。
- パラメータ
- fd: 仮想ネットワークカードの fd、整数
- buf: 書き込むデータ、文字列
- 戻り値
- 失敗すると「nil、error_msg」が返されます
- 正常に書き込まれたバイト数、整数
skt.api.get_from_skcp(skcp, 名前)
skcp オブジェクトの対応するフィールド値、つまり「skcp.name」を取得します。
- パラメータ
- skcpオブジェクト
- name: skcp のフィールド名、現在は「fd」フィールドのみをサポート、文字列
- 戻り値
- 失敗すると「nil、error_msg」が返されます
- 名前、任意の値に対応する値を正常に返します。
skt.api.get_ms()
現在のシステムの 1970 年以降のミリ秒数を取得します。
skt.api.hton32(i)
32 ビット整数変数をホスト バイト オーダーからネットワーク バイト オーダーに変換します。
skt.api.ntoh32(i)
32 ビット整数変数をネットワーク バイト オーダーからホスト バイト オーダーに変換します。
skt.api.band(a, b)
2 つの整数に対してビットごとの論理 AND 演算を実行し、結果を返します。
skt.api.bor(a, b)
2 つの整数に対してビットごとの論理 OR 演算を実行し、結果を返します。
skt.api.bxor(a, b)
2 つの整数に対してビット単位の XOR 演算を実行し、結果を返します。
skt.api.blshift(i, n)
整数を左に n ビットシフトして結果を返します
skt.api.brshift(i, n)
整数を右に n ビットシフトして結果を返します
skt.api.lookup_dns(ドメイン)
ドメイン名の解決
- パラメータ
- 戻り値
- 対応する IP をドット形式 (IPV4) の文字列で返します。
Lua スクリプトが実装する必要があるコールバック インターフェイス
「skt.cb.*」は、skcptun コールバックのさまざまな起動モードに応じてさまざまなインターフェイスを実装する必要があります。
skt.cb.on_init(ループ)
スクリプトの開始時に呼び出される最初のコールバック インターフェイス。一度だけ呼び出されます。
- 有効範囲: すべてのモード
- パラメータ
- 戻り値: なし
skt.cb.on_skcp_accept(skcp, cid)
skcp サーバーは cid を正常に作成し、接続ごとに 1 回だけ呼び出されます。
- 有効な範囲: 「proxy_server」、「tun_server」
- パラメータ
- skcpオブジェクト
- cid: skcp の接続 ID、整数
- 戻り値: なし
skt.cb.on_skcp_check_ticket(skcp, チケット)
skcp サーバーはチケットが正しいかどうかを検証します。
- 有効な範囲: 「proxy_server」、「tun_server」
- パラメータ
- skcpオブジェクト
- ticket: 検証が必要なチケット、文字列
- 戻り値:
- 検証が成功した場合は 0 を返します
- 検証が失敗した場合は、ゼロ以外の値が返されます。
skt.cb.on_skcp_recv_cid(skcp, cid)
skcp は、skcp サーバーとの接続が正常に確立されたことを示す cid を受け取ります。つまり、「skt.api.skcp_req_cid(skcp, ticket)」の非同期構造体が返されます。
- 有効な範囲: "proxy_client"、"tun_client"
- パラメータ
- skcpオブジェクト
- cid: skcp の接続 ID、整数
- 戻り値: なし
skt.cb.on_skcp_recv_data(skcp、cid、buf)
skcpはcidの接続に対応するデータを受信します。
- 有効範囲: すべてのモード
- パラメータ
- skcpオブジェクト
- cid: skcp の接続 ID、整数
- buf: 受信したメッセージの内容、文字列
- 戻り値: なし
skt.cb.on_skcp_close(skcp, cid)
skcp が接続を閉じるときのコールバックは、通常、タイムアウトまたはピアからの閉じるコマンドの受信によって発生する可能性があります。この時点では接続は実際には閉じられていません。
- 有効範囲: すべてのモード
- パラメータ
- skcpオブジェクト
- cid: skcp の接続 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
結論は
- 同一のネットワーク環境下では、速度向上効果は約30%~40%となります。
知らせ
- 個人利用向けに書き終えたところ、機能は完成しつつあります
- 暗号化を高速化するためにこれを使用しないでください。 sock5 プロキシ?