stunnel + DeleGate でトンネルを掘る

某所は外に出るのにport 80と443だけを通すproxy serverがあるという環境なのだが、 これまでは仙石浩明氏の stone を使ってSSHで外に出るトンネルを 掘っていた。 前の記事 でも書いたようにstoneが最近のOpenSSLに追従できていない状態なので、 別な方法でトンネルを掘ろうと試してみた。

DeleGate

壁の外のサーバでpkgでdelegateをインストールして、

/usr/local/sbin/delegated -P127.0.0.1:1080:__1:1080 SERVER=socks ADMIN=my@address.jp > /dev/null 2>&1

で起動する。これでDeleGateがport 1080で待ち受けるSOCKSサーバになる。

stunnel

stunnelでトンネルを掘る。

鍵作成

OpenSSLで鍵を適当に作成。

% openssl genrsa -aes256 -out ca.key 2048
% openssl req -new -key ca.key -out ca.csr -subj "/CN=TestCA"
% openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt -days 9999

% openssl genrsa -aes256 -out server.key 2048
% openssl req -new -key server.key -out server.csr -subj "/CN=test.example.com"
% openssl x509 -req -CA ca.crt -CAkey ca.key -set_serial 1 -in server.csr -out server.crt -days 9999

% openssl genrsa -aes256 -out client.key 2048
% openssl req -new -key client.key -out client.csr -subj "/CN=TestClient"
% openssl x509 -req -CA ca.crt -CAkey ca.key -set_serial 2 -in client.csr -out client.crt -days 9999

% openssl rsa -in server.key -out server-nopass.key
% openssl rsa -in client.key -out client-nopass.key

壁の外のサーバ

/usr/local/etc/stunnelに先ほど作成したca.crt server-nopass.key server.crtの3つを置き、

chown root:wheel ca.crt server-nopass.key server.crt
chmod 400 ca.crt server-nopass.key server.crt
mkdir /var/run/stunnel
chown stunnel:stunnel /var/run/stunnel

/etc/rc.confに以下を追加

stunnel_enable="YES"
stunnel_pidfile="/var/run/stunnel/stunnel.pid"

/usr/local/etc/stunnel/stunnel.conf

cert = /usr/local/etc/stunnel/server.crt
key = /usr/local/etc/stunnel/server-nopass.key
CAfile = /usr/local/etc/stunnel/ca.crt
setuid = stunnel
setgid = stunnel
chroot = /var/run/stunnel
pid = /stunnel.pid
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
verify = 2
debug = local1.notice

[SOCKS over SSL]
accept = 443
connect = 1080
TIMEOUTclose = 0

SOCKSで待ち受けるport 1080はlocal addressのみにbindしているので危険はあまりないが、 stunnelが待ち受けるport 443は攻撃を防ぐためにfirewallを適宜設定しておく。

壁の中のサーバ

/usr/local/etc/stunnelにca.crt client-nopass.key client.crtの3つを置き、

chown root:wheel ca.crt server-nopass.key server.crt
chmod 400 ca.crt server-nopass.key server.crt
mkdir /var/run/stunnel
chown stunnel:stunnel /var/run/stunnel

しておく。/etc/rc.confに追加する内容は壁の外のサーバと同じ。

/usr/local/etc/stunnel/stunnel.conf

cert = /usr/local/etc/stunnel/client.crt
key = /usr/local/etc/stunnel/client-nopass.key
CAfile = /usr/local/etc/stunnel/ca.crt

debug = local1.notice
verify = 2
options = NO_SSLv2
sslVersion = TLSv1

setuid = stunnel
setgid = stunnel
pid = /stunnel.pid
chroot = /var/run/stunnel

[socks_over_ssl]
client = yes
accept = 1080
protocol = connect
protocolHost = 壁の外のサーバ:443
connect = 壁のfirewall:port

stunnelのログはsyslogのlocal1ファシリティに出力されるので、/etc/syslog.confを適宜修正しておく。 これで、壁の中のサーバのport 1080をSOCKSサーバとして指定すれば外に出ることができる。