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
[/code]
こんなエラーが出てしまった
[code]
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: [linux–ssl] Error 2[/code]
Debian Squeezeで発生。Lennyでは出ませんでした。
どうやらglibc 2.8 以降では、この構造体の定義を得るためには機能検査マクロ _GNU_SOURCE を定義しなければならないようです。
解決方法としては、Makefileの以下の記述部分に、-D_GNU_SOURCEを追加することで正常にコンパイルできるようになりました。
[code]
$(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
[/code]
再度実行。
[code]
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]
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]
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で監視するなどの設定が必要だと思います。