TCP および UDP の パケットリピータ stone の簡単な使用方法
[履歴] [最終更新] (2019/01/23 16:26:02)
最近の投稿
注目の記事

概要

こちらで公開されている stone という小型のツールを用いると、飛び石としてパケット転送を行う中継サーバを用意することができます。実際には多機能なツールですがここでは最も簡単な使用例を紹介します。

ビルド手順

ダウンロード

公式サイトから最新のもの stone version 2.3e をダウンロードします。

解凍およびビルド

Linux で SSL 通信の機能も含めたバイナリをビルドするためには以下のようにします。

$ tar zxvf stone-2.3e.tar.gz
$ cd stone-2.3d-2.3.2.7/
$ make linux-ssl

エラーが出る場合は以下のように Makefile を編集して -D_GNU_SOURCE を追記してから再度 make します。

 linux:
-  $(MAKE) FLAGS="-O -Wall -DCPP='\"/usr/bin/cpp -traditional\"' -DPTHREAD
     -DUNIX_DAEMON -DPRCTL -DSO_ORIGINAL_DST=80 -DUSE_EPOLL $(FLAGS)" LIBS="-lpthread $(LIBS)" stone
+  $(MAKE) FLAGS="-O -Wall -DCPP='\"/usr/bin/cpp -traditional\"' -DPTHREAD
     -DUNIX_DAEMON -DPRCTL -DSO_ORIGINAL_DST=80 -DUSE_EPOLL -D_GNU_SOURCE $(FLAGS)" LIBS="-lpthread $(LIBS)" stone

ビルド結果のバイナリは例えば /usr/local/bin に設置します。

$ sudo mv stone /usr/local/bin/
$ which stone
/usr/local/bin/stone

使用例

まず、あるターミナルで以下のコマンドを実行しておきます。

$ stone 127.0.0.1:22 10022
May 27 00:16:04.535048 139811526662080 start (2.3e) [4504]
May 27 00:16:04.543449 139811526662080 stone 3: 127.0.0.1:ssh <- 0.0.0.0:10022

その状態で、別のターミナルで以下のコマンドを実行します。

$ telnet 127.0.0.1 10022
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
SSH-2.0-OpenSSH_5.3

確かに「stone を動作させているマシンの 10022 番ポート」へのパケットが「127.0.0.1 の 22 番ポート」に転送されました。実用的には 127.0.0.1 ではなく LAN 内の PC のプライベート IP を指定して使用することになります。アクセス元 IP を制限したい場合は以下のようにします。

$ stone 127.0.0.1:22 アクセス元IP:10022

(参考) コマンドを組み合わせる方法

一時的な用途であれば、簡易的にいくつかのコマンドを組み合わせて、同様にパケットリピータを実現できます。

pc --ssh--> vagrant --http--> www.example.com:80

検証用のコマンド

ssh vagrant
curl -H 'Host: www.example.com' localhost:8888

SSH トンネルを利用する方法

-fN は必須ではありませんが、ポート転送をバックグラウンドで行うために指定しています。

localhost に ssh できる場合

ssh vagrant
ssh localhost -fN -L 8888:www.example.com:80

localhost に ssh できない場合

ssh vagrant -fN -L 1234:www.example.com:80
ssh vagrant -fN -R 8888:localhost:1234

nc (netcat/ncat) を利用する方法

サーバとして機能する前段の nc の標準出力を、クライアントとして機能する後段の nc にパイプで渡します。クライアント nc が受け取ったレスポンスは fifo ファイルでパイプしてサーバ nc に渡します。一回の HTTP 通信が終了すると nc は終了するため、while で繰り返し実行しています。

CentOS 等

mkfifo /tmp/fifo
while /usr/bin/true; do nc -l 8888 < /tmp/fifo | nc www.example.com 80 > /tmp/fifo; done

Debian 等

mkfifo /tmp/fifo
while /bin/true; do nc -l -p 8888 < /tmp/fifo | nc -q 0 www.example.com 80 > /tmp/fifo; done

応用として -x に対応している nc の場合は TCP プロキシサーバを経由して以下のようなこともできます。

mkfifo /tmp/fifo
while /bin/true; do nc.openbsd -l -p 8888 < /tmp/fifo | nc.openbsd -x proxy.example.com:1080 -q 0 internal.example.com 80 > /tmp/fifo; done
curl http://localhost:8888

curl の --socks5-hostname オプションを利用するとより簡単です。

curl --socks5-hostname proxy.example.com:1080 http://internal.example.com

socat を利用する方法

sudo apt install socat
sudo yum install socat
socat TCP4-LISTEN:8888,fork TCP4:www.example.com:80

ログを監視して通信を切断する試験

ログファイルに 'xxxx' という文字列が出現したら www.example.com との通信を 5 秒間切断するためには以下のようにします。

./myscript.bash

#!/bin/bash
echo "./stop_packet_repeat.bash"
./stop_packet_repeat.bash
echo "sleep 5"
sleep 5
echo "./start_packet_repeat.bash &"
./start_packet_repeat.bash &

./start_packet_repeat.bash

#!/bin/bash
if [ ! -e /tmp/fifo ]; then
    mkfifo /tmp/fifo
fi
while /bin/true; do nc -l -p 8888 < /tmp/fifo | nc -q 0 www.example.com 80 > /tmp/fifo; done

./stop_packet_repeat.bash (pkill)

#!/bin/bash
pkill -9 -f start_packet_repeat.bash
pkill -9 -f nc

実行例 (lsof)

lsof -i:8888
./start_packet_repeat.bash &
tailf /var/log/mylog.txt | grep --line-buffered 'xxxx' | while read line; do ./myscript.bash "$line"; done

別ターミナル

sudo sh -c "echo 'xxxx xxxx' >> /var/log/mylog.txt"
curl -H 'Host: www.example.com' localhost:8888

ルーティングテーブルを書き換える方法 (参考)

パケットリピータとは関係ありませんが、ログを監視して通信を切断する試験については、ルーティングテーブルを書き換えるのが簡単です。ip コマンドを利用します。

ip アドレスの確認

vagrant@stretch:/vagrant$ host www.example.com
www.example.com has address 93.184.216.34
www.example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:194

ルーティングテーブルの確認

vagrant@stretch:/vagrant$ ip r
default via 10.0.2.2 dev eth0 
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 

./myscript.bash

#!/bin/bash
sudo ip route add 93.184.216.34/32 via 127.0.0.1 dev lo
sleep 5
sudo ip route del 93.184.216.34/32
関連ページ
    ファイル内容を再帰的に検索 (grep) find コマンドはファイル名についてディレクトリを再帰的に検索します。ファイルの内容について指定したディレクトリ以下を再帰的に検索するためには grep に -r オプションを付与します。その際 -n および -i オプションも付与しておくと便利です。未来創発 NRI grep です。
    コマンドのエイリアスを登録する (update-alternatives) mybin という名前のコマンドを登録 sudo update-alternatives --install /usr/local/bin/mybin mybin /usr/bin/echo 10 sudo update-alternatives --install /usr/local/bin/mybin mybin