hero_picture

stoneを使ってIRCのSSL暗号化を行う

2013/01/16

stone は、アプリケーションレベルの TCP & UDP リピーターです。

stone – http://www.gcd.org/sengoku/stone/Welcome.ja.html

IRCサーバーはSSL暗号化に対応しているものが少なく、データがすべて平文でやりとりされてしまう。

stoneは任意のポートからポートへトンネルをつくる事が出来るアプリケーションなんですが、

stoneがSSLに対応している為、こちらを使ってIRCSSL対応を行います。

これはポートを待ち受けるアプリケーションであればどのアプリケーションでも暗号化可能かと思います。

イメージしにくいかもしれないので以下がイメージ図。

IRCサーバーは6667で待ち受けているアプリケーション。

stoneを使う事で6668ポートと6667ポートを中継し、クライアントは6668ポートに繋ぐ事でIRCへ接続できる。

またstoneはSSLに対応している為、6668ポートはSSL暗号化を利用する事ができる。

stoneのインストール

すこしハマったので詳細を記述します。

[code]

cd /usr/local/src

wget http://www.gcd.org/sengoku/stone/stone-2.3e.tar.gz

tar zxvf stone-2.3e.tar.gz

make linuxssl

[/code]

こんなエラーが出てしまった

[code]

# make linuxssl

make TARGET=linux ssl_stone LIBS=”-ldl”

make[1]: Entering directory /usr/local/src/stone-2.3d-2.3.2.7'make FLAGS="-DUSE_POP -DUSE_SSL " LIBS="-ldl -lssl -lcrypto" linuxmake[2]: Entering directory/usr/local/src/stone-2.3d-2.3.2.7′make FLAGS=”-O -Wall -DCPP=’\”/usr/bin/cpp -traditional\”‘ -DPTHREAD -DUNIX_DAEMON -DPRCTL -DSO_ORIGINAL_DST=80 -DUSE_EPOLL -DUSE_POP -DUSE_SSL ” LIBS=”-lpthread -ldl -lssl -lcrypto” stonemake[3]: Entering directory /usr/local/src/stone-2.3d-2.3.2.7'cc -O -Wall -DCPP='"/usr/bin/cpp -traditional"' -DPTHREAD -DUNIX_DAEMON -DPRCTL -DSO_ORIGINAL_DST=80 -DUSE_EPOLL -DUSE_POP -DUSE_SSL -o stone stone.c -lpthread -ldl -lssl -lcryptostone.c: In function ‘saDup’:stone.c:1558: warning: cast from pointer to integer of different sizestone.c: In function ‘sendPairUDPbuf’:stone.c:3023: warning: cast from pointer to integer of different sizestone.c: In function ‘freePair’:stone.c:3644: warning: cast from pointer to integer of different sizestone.c: In function ‘doconnect’:stone.c:3883: warning: cast from pointer to integer of different sizestone.c: In function ‘acceptPair’:stone.c:4072: warning: cast from pointer to integer of different sizestone.c: In function ‘strnUser’:stone.c:4509: error: dereferencing pointer to incomplete typestone.c:4524: error: dereferencing pointer to incomplete typestone.c:4536: error: dereferencing pointer to incomplete typestone.c:4551: error: dereferencing pointer to incomplete typestone.c:4557: error: dereferencing pointer to incomplete typestone.c: In function ‘proto2fdset’:stone.c:6239: warning: cast from pointer to integer of different sizestone.c:6300: warning: cast from pointer to integer of different sizestone.c: In function ‘dispatch’:stone.c:6916: warning: cast from pointer to integer of different sizestone.c: In function ‘newMatch’:stone.c:7070: warning: cast from pointer to integer of different sizestone.c: In function ‘freeMatch’:stone.c:7084: warning: cast from pointer to integer of different sizestone.c: In function ‘initialize’:stone.c:10178: warning: cast from pointer to integer of different sizemake[3]: *** [stone] Error 1make[3]: Leaving directory/usr/local/src/stone-2.3d-2.3.2.7′make[2]: [linux] Error 2make[2]: Leaving directory /usr/local/src/stone-2.3d-2.3.2.7'make[1]: *** [ssl_stone] Error 2make[1]: Leaving directory/usr/local/src/stone-2.3d-2.3.2.7′make: [linuxssl] Error 2[/code]

Debian Squeezeで発生。Lennyでは出ませんでした。

どうやらglibc 2.8 以降では、この構造体の定義を得るためには機能検査マクロ _GNU_SOURCE を定義しなければならないようです。

解決方法としては、Makefileの以下の記述部分に、-D_GNU_SOURCEを追加することで正常にコンパイルできるようになりました。

(参考) http://typex2.wordpress.com/2009/10/25/stone%E3%82%92linux%E3%81%A7%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%81%99%E3%82%8B/

[code]

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

linux:

$(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

[/code]

再度実行。

[code]

# make linuxssl

make TARGET=linux ssl_stone LIBS=”-ldl”

make[1]: Entering directory /usr/local/src/stone-2.3d-2.3.2.7'make FLAGS="-DUSE_POP -DUSE_SSL " LIBS="-ldl -lssl -lcrypto" linuxmake[2]: Entering directory/usr/local/src/stone-2.3d-2.3.2.7′make FLAGS=”-O -Wall -DCPP=’\”/usr/bin/cpp -traditional\”‘ -DPTHREAD -DUNIX_DAEMON -DPRCTL -DSO_ORIGINAL_DST=80 -DUSE_EPOLL -D_GNU_SOURCE -DUSE_POP -DUSE_SSL ” LIBS=”-lpthread -ldl -lssl -lcrypto” stonemake[3]: Entering directory /usr/local/src/stone-2.3d-2.3.2.7'cc -O -Wall -DCPP='"/usr/bin/cpp -traditional"' -DPTHREAD -DUNIX_DAEMON -DPRCTL -DSO_ORIGINAL_DST=80 -DUSE_EPOLL -D_GNU_SOURCE -DUSE_POP -DUSE_SSL -o stone stone.c -lpthread -ldl -lssl -lcryptostone.c: In function ‘saDup’:stone.c:1558: warning: cast from pointer to integer of different sizestone.c: In function ‘sendPairUDPbuf’:stone.c:3023: warning: cast from pointer to integer of different sizestone.c: In function ‘freePair’:stone.c:3644: warning: cast from pointer to integer of different sizestone.c: In function ‘doconnect’:stone.c:3883: warning: cast from pointer to integer of different sizestone.c: In function ‘acceptPair’:stone.c:4072: warning: cast from pointer to integer of different sizestone.c: In function ‘proto2fdset’:stone.c:6239: warning: cast from pointer to integer of different sizestone.c:6300: warning: cast from pointer to integer of different sizestone.c: In function ‘dispatch’:stone.c:6916: warning: cast from pointer to integer of different sizestone.c: In function ‘newMatch’:stone.c:7070: warning: cast from pointer to integer of different sizestone.c: In function ‘freeMatch’:stone.c:7084: warning: cast from pointer to integer of different sizestone.c: In function ‘initialize’:stone.c:10178: warning: cast from pointer to integer of different sizemake[3]: Leaving directory/usr/local/src/stone-2.3d-2.3.2.7′make[2]: Leaving directory /usr/local/src/stone-2.3d-2.3.2.7'make[1]: Leaving directory/usr/local/src/stone-2.3d-2.3.2.7′[/code]

なんか警告は出てますが無事コンパイル完了しました。

パスが通る位置にコンパイル済のstoneを移動

[code]

cp -rfpa stone /usr/local/bin/

[/code]

動作テスト

動いてるポートへ別ポートから接続できるかテスト。(6668から6667へ接続例)

[code]

stone localhost:6667 6668

Mar 27 12:00:18.903642 139940579038976 start (2.3e) [21488]

Mar 27 12:00:18.904514 139940579038976 stone 3: 127.0.0.1:ircd <- 0.0.0.0:6668

stone localhost:6667 6668

[/code]

これでircサーバーに6667でも6668でも接続が可能になる。

次は暗号化して待ち受けテスト

[code]

stone localhost:6667 6668/ssl

Mar 27 12:19:26.297086 140086834108160 start (2.3e) [23145]

Mar 27 12:19:26.297835 140086834108160 SSL_CTX_use_PrivateKey_file(/usr/lib/ssl/certs/stone.pem) error:02001002:system library:fopen:No such file or directory

[/code]

証明書がないというエラーが出て立ち上がらない。

どうやらデフォルトで/usr/lib/ssl/certs/stone.pemにある証明書&keyを利用するようなのでここに証明書を作成する。(要openssl)

[code]

openssl req -new -outform pem -out stone.cert -newkey rsa:2048 -keyout stone.key -nodes -rand ./rand.pat -x509 -batch -days 3560

cat stone.cert stone.key > stone.pem

cp stone.pem /usr/lib/ssl/certs/

[/code]

2048bitで3560(10年)使用できる鍵を作成。

普段使用している証明書と鍵でも

証明書ファイル 鍵ファイル の順番のファイルを作ればOKです。

改めてSSL接続テスト。

[code]

stone localhost:6667 6668/ssl

Mar 27 12:34:04.695961 140533134583552 start (2.3e) [24813]

Mar 27 12:34:04.697198 140533134583552 stone 3: 127.0.0.1:ircd <- 0.0.0.0:6668/ssl

[/code]

6668ポートにSSL接続できる事が確認できます。

これでSSLでの待ち受けもOKです。

起動

こんな感じで起動

[code]

stone localhost:6667 6668/ssl >& /dev/null &

[/code]

Linuxファイアウォール設定でircの6667ポートを閉じて6668をOPENにする。

あとはIRCクライアント側(LimeChatとか)の設定で 6668ポートにSSLで接続できるようになります。

備考

今のところ僕の環境では問題ないですが、クリティカルな環境ではstoneが落ちたりするのを防ぐ為に

プロセス監視を行うかdaemontoolsで監視するなどの設定が必要だと思います。