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" 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:
[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" 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で監視するなどの設定が必要だと思います。