stone は、アプリケーションレベルの TCP & UDP リピーターです。 stone - http://www.gcd.org/sengoku/stone/Welcome.ja.html
IRCサーバーはSSL暗号化に対応しているものが少なく、データがすべて平文でやりとりされてしまう。 stoneは任意のポートからポートへトンネルをつくる事が出来るアプリケーションなんですが、 stoneがSSLに対応している為、こちらを使ってIRCのSSL対応を行います。
これはポートを待ち受けるアプリケーションであればどのアプリケーションでも暗号化可能かと思います。
イメージしにくいかもしれないので以下がイメージ図。
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 linux-ssl [/code]
こんなエラーが出てしまった
[code]
# make linux-ssl
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" linux
make[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" stone
make[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 -lcrypto
stone.c: In function ‘saDup’:
stone.c:1558: warning: cast from pointer to integer of different size
stone.c: In function ‘sendPairUDPbuf’:
stone.c:3023: warning: cast from pointer to integer of different size
stone.c: In function ‘freePair’:
stone.c:3644: warning: cast from pointer to integer of different size
stone.c: In function ‘doconnect’:
stone.c:3883: warning: cast from pointer to integer of different size
stone.c: In function ‘acceptPair’:
stone.c:4072: warning: cast from pointer to integer of different size
stone.c: In function ‘strnUser’:
stone.c:4509: error: dereferencing pointer to incomplete type
stone.c:4524: error: dereferencing pointer to incomplete type
stone.c:4536: error: dereferencing pointer to incomplete type
stone.c:4551: error: dereferencing pointer to incomplete type
stone.c:4557: error: dereferencing pointer to incomplete type
stone.c: In function ‘proto2fdset’:
stone.c:6239: warning: cast from pointer to integer of different size
stone.c:6300: warning: cast from pointer to integer of different size
stone.c: In function ‘dispatch’:
stone.c:6916: warning: cast from pointer to integer of different size
stone.c: In function ‘newMatch’:
stone.c:7070: warning: cast from pointer to integer of different size
stone.c: In function ‘freeMatch’:
stone.c:7084: warning: cast from pointer to integer of different size
stone.c: In function ‘initialize’:
stone.c:10178: warning: cast from pointer to integer of different size
make[3]: *** [stone] Error 1
make[3]: Leaving directory
/usr/local/src/stone-2.3d-2.3.2.7'
make[2]: [linux] Error 2
make[2]: Leaving directory /usr/local/src/stone-2.3d-2.3.2.7'
make[1]: *** [ssl_stone] Error 2
make[1]: Leaving directory
/usr/local/src/stone-2.3d-2.3.2.7'
make: [linux-ssl] 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 linux-ssl
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" linux
make[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" stone
make[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 -lcrypto
stone.c: In function ‘saDup’:
stone.c:1558: warning: cast from pointer to integer of different size
stone.c: In function ‘sendPairUDPbuf’:
stone.c:3023: warning: cast from pointer to integer of different size
stone.c: In function ‘freePair’:
stone.c:3644: warning: cast from pointer to integer of different size
stone.c: In function ‘doconnect’:
stone.c:3883: warning: cast from pointer to integer of different size
stone.c: In function ‘acceptPair’:
stone.c:4072: warning: cast from pointer to integer of different size
stone.c: In function ‘proto2fdset’:
stone.c:6239: warning: cast from pointer to integer of different size
stone.c:6300: warning: cast from pointer to integer of different size
stone.c: In function ‘dispatch’:
stone.c:6916: warning: cast from pointer to integer of different size
stone.c: In function ‘newMatch’:
stone.c:7070: warning: cast from pointer to integer of different size
stone.c: In function ‘freeMatch’:
stone.c:7084: warning: cast from pointer to integer of different size
stone.c: In function ‘initialize’:
stone.c:10178: warning: cast from pointer to integer of different size
make[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で監視するなどの設定が必要だと思います。