こちらで公開されている 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
-fN
は必須ではありませんが、ポート転送をバックグラウンドで行うために指定しています。
ssh vagrant
ssh localhost -fN -L 8888:www.example.com:80
ssh vagrant -fN -L 1234:www.example.com:80
ssh vagrant -fN -R 8888:localhost:1234
サーバとして機能する前段の nc の標準出力を、クライアントとして機能する後段の nc にパイプで渡します。クライアント nc が受け取ったレスポンスは fifo ファイルでパイプしてサーバ nc に渡します。一回の HTTP 通信が終了すると nc は終了するため、while で繰り返し実行しています。
mkfifo /tmp/fifo
while /usr/bin/true; do nc -l 8888 < /tmp/fifo | nc www.example.com 80 > /tmp/fifo; done
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
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