sslhで80空いたマシンでhttpだけじゃなくsshも待ち受けるようにする

sslh でport443 を有効活用して、sshhttpsも同時に待ち受けする。 - それマグで!
http://takuya-1st.hatenablog.jp/entry/2016/10/14/144244
これはスバラシイ。


ご本家は、このへんかな?
sslh -- A ssl/ssh multiplexer
https://github.com/yrutschle/sslh
ssl/ssh multiplexer
http://www.rutschle.net/tech/sslh.shtml


sslhの負荷耐性が気になるところ。
httpもあるから、80を使い回すこともできそうね。
負荷少ないとこでしばらく試すか。

CentOS7系でパッケージを探す

あれば御の字。

# yum search sslh
(snip)
Warning: No matches found for: sslh
No matches found

悲しい。

# yum search --enablerepo=epel sslh
(snip)
============================== N/S matched: sslh ===============================
sslh.x86_64 : Applicative protocol(SSL/SSH) multiplexer

EPELにはあった。

sslhパッケージの導入

入れる。

# yum install --enablerepo=epel sslh
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.jaist.ac.jp
 * epel: ftp.jaist.ac.jp
 * extras: ftp.jaist.ac.jp
 * updates: ftp.jaist.ac.jp
Resolving Dependencies
--> Running transaction check
---> Package sslh.x86_64 0:1.18-1.el7 will be installed
--> Processing Dependency: libconfig.so.9()(64bit) for package: sslh-1.18-1.el7.x86_64
--> Running transaction check
---> Package libconfig.x86_64 0:1.4.9-5.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package            Arch            Version                 Repository     Size
================================================================================
Installing:
 sslh               x86_64          1.18-1.el7              epel           51 k
Installing for dependencies:
 libconfig          x86_64          1.4.9-5.el7             base           59 k

Transaction Summary
================================================================================
Install  1 Package (+1 Dependent package)

Total download size: 110 k
Installed size: 327 k
Is this ok [y/d/N]: y
Downloading packages:
(1/2): libconfig-1.4.9-5.el7.x86_64.rpm                    |  59 kB   00:00
(2/2): sslh-1.18-1.el7.x86_64.rpm                          |  51 kB   00:00
--------------------------------------------------------------------------------
Total                                              277 kB/s | 110 kB  00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : libconfig-1.4.9-5.el7.x86_64                                 1/2
  Installing : sslh-1.18-1.el7.x86_64                                       2/2
  Verifying  : sslh-1.18-1.el7.x86_64                                       1/2
  Verifying  : libconfig-1.4.9-5.el7.x86_64                                 2/2

Installed:
  sslh.x86_64 0:1.18-1.el7

Dependency Installed:
  libconfig.x86_64 0:1.4.9-5.el7

Complete!

インストールされた。
本家の最新リリースと同じバージョンなので、少し安心。

# rpm -ql sslh
/etc/sslh.cfg
/etc/sysconfig/sslh
/usr/lib/systemd/system/sslh.service
/usr/lib/systemd/system/sslh.socket
/usr/sbin/sslh
/usr/sbin/sslh-select
/usr/share/doc/sslh-1.18
/usr/share/doc/sslh-1.18/ChangeLog
/usr/share/doc/sslh-1.18/README.md
/usr/share/doc/sslh-1.18/example.cfg
/usr/share/licenses/sslh-1.18
/usr/share/licenses/sslh-1.18/COPYING
/usr/share/man/man8/sslh.8.gz

systemd管轄では、sslh.service、sslh.socketの2つがあった。

# systemctl status sslh
● sslh.service - SSL/SSH multiplexer
   Loaded: loaded (/usr/lib/systemd/system/sslh.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:sslh(8)

デフォルトでは起動していない。

Apacheの設定変更

ターゲットになるport80で起動しているapacheを停止、待受けするアドレスを変更する。

# systemctl stop httpd.service
# vi /etc/httpd/conf/httpd.conf
# Listen 80
Listen 127.0.0.1:80
# systemctl start httpd.service

外からブラウザでアクセスできないのを確認する。

sshlの設定と起動

sshlの設定を行う。
テンプレは、/usr/share/doc/sslh-1.18/example.cfgにある。
libconfigベースの設定ファイルになっている。
最低限の設定は、デフォルトで設定済み。

# cat /etc/sslh.cfg
# This is a basic configuration file that should provide
# sensible values for "standard" setup.

verbose: false;
foreground: true;
inetd: false;
numeric: false;
transparent: false;
timeout: 2;
user: "sslh";


# Change hostname with your external address name.
listen:
(
    { host: "thelonious"; port: "443"; }
);

protocols:
(
     { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; },
     { name: "openvpn"; host: "localhost"; port: "1194"; },
     { name: "xmpp"; host: "localhost"; port: "5222"; },
     { name: "http"; host: "localhost"; port: "80"; },
     { name: "ssl"; host: "localhost"; port: "443"; log_level: 0; },
     { name: "anyprot"; host: "localhost"; port: "443"; }
);

待受けを書き換えるだけで機能しそうだ。
不要な中継は削っておく。

# vi /etc/sslh.cfg
listen:
(
    { host: "192.168.0.3"; port: "80"; }
);

protocols:
(
     { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; },
     { name: "http"; host: "localhost"; port: "80"; },
);


起動する。

# systemctl enable sslh
Created symlink from /etc/systemd/system/multi-user.target.wants/sslh.service to /usr/lib/systemd/system/sslh.service.
# systemctl start sslh
# systemctl status sslh
● sslh.service - SSL/SSH multiplexer
   Loaded: loaded (/usr/lib/systemd/system/sslh.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Mon 2016-11-07 21:09:57 JST; 6s ago
     Docs: man:sslh(8)
  Process: 20739 ExecStart=/usr/sbin/sslh $DAEMON_OPTS (code=exited, status=1/FAILURE)
 Main PID: 20739 (code=exited, status=1/FAILURE)

Nov 07 21:09:57 TGT01 systemd[1]: Started SSL/SSH multiplexer.
Nov 07 21:09:57 TGT01 systemd[1]: Starting SSL/SSH multiplexer...
Nov 07 21:09:57 TGT01 sslh[20739]: /etc/sslh.cfg:23:syntax error
Nov 07 21:09:57 TGT01 systemd[1]: sslh.service: main process exited, cod...RE
Nov 07 21:09:57 TGT01 systemd[1]: Unit sslh.service entered failed state.
Nov 07 21:09:57 TGT01 systemd[1]: sslh.service failed.
Hint: Some lines were ellipsized, use -l to show in full.

あら、ダメだわ。
これかな?

     { name: "http"; host: "localhost"; port: "80"; }

リトライ。

# systemctl start sslh
# systemctl status sslh -l
● sslh.service - SSL/SSH multiplexer
   Loaded: loaded (/usr/lib/systemd/system/sslh.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2016-11-07 21:13:41 JST; 4s ago
     Docs: man:sslh(8)
 Main PID: 20793 (sslh)
   CGroup: /system.slice/sslh.service
           ├─20793 /usr/sbin/sslh -F/etc/sslh.cfg
           └─20794 /usr/sbin/sslh -F/etc/sslh.cfg

Nov 07 21:13:41 TGT01 systemd[1]: Started SSL/SSH multiplexer.
Nov 07 21:13:41 TGT01 systemd[1]: Starting SSL/SSH multiplexer...
Nov 07 21:13:41 TGT01 sslh[20793]: sslh-fork 38447c815821ae8b6379d8005628ea3c9f94f1ee started

動作確認

ブラウザでport80にアクセスしてみる。
おお、普通にアクセスできる。


sshでアクセスしてみる。

$ ssh kinneko3@TGT01 -p80
The authenticity of host '[TGT01]:80 ([TGT01]:80)' can't be established.
RSA key fingerprint is 7c:1d:e7:06:09:8d:11:56:70:a7:1f:8e:79:2b:20:e4.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[TGT01]:80' (RSA) to the list of known hosts.
Last login: Mon Nov  7 21:17:19 2016 from localhost
[kinneko3@TGT01 ~]$

普通に入れた。


これって、sslhを隠蔽して、隠蔽sshdを別にlocalhost用に立てれば、簡単なバックドアになりそうね。

しばらく放置するとセッション切れる

sslh側でなんかしてるのかも。
設定のテンプレを眺めると、sshはこんな風に設定されている。

     { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; keepalive: true; },

keepalive: trueがミソかも。

# vi /etc/sslh.cfg
     { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; keepalive: true; },
# systemctl restart sslh.service
# systemctl status sslh.service
● sslh.service - SSL/SSH multiplexer
   Loaded: loaded (/usr/lib/systemd/system/sslh.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2016-11-07 23:46:37 JST; 8s ago
     Docs: man:sslh(8)
 Main PID: 22877 (sslh)
   CGroup: /system.slice/sslh.service
           ├─20937 /usr/sbin/sslh -F/etc/sslh.cfg
           ├─21558 /usr/sbin/sslh -F/etc/sslh.cfg
           ├─21777 /usr/sbin/sslh -F/etc/sslh.cfg
           ├─22750 /usr/sbin/sslh -F/etc/sslh.cfg
           ├─22877 /usr/sbin/sslh -F/etc/sslh.cfg
           └─22878 /usr/sbin/sslh -F/etc/sslh.cfg

Nov 07 23:46:37 TGT01 systemd[1]: Started SSL/SSH multiplexer.
Nov 07 23:46:37 TGT01 systemd[1]: Starting SSL/SSH multiplexer...
Nov 07 23:46:37 TGT01 sslh[22877]: sslh-fork 38447c815821ae8b6379d800562...ed
Hint: Some lines were ellipsized, use -l to show in full.

やっぱり、しばらく端末放置すると切れちゃうのねん。

少し設定見直し

timeout: 2は、中継選択時のタイムアウトで、サービスのじゃないよな...
タイムアウトで落ちる先を決めておく。

on-timeout: "http";

なんか、sshのサイトでは、probe: "builtin"が推奨されているようなので付けておく。プロトコル判定時の正規表現処理が、やや早くなる。

     { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; keepalive: true; probe: "builtin";},

service: "ssh"は、TCPWapperを使っている時にはいるらしい。

つながらない

こんなメッセージが出るようになった。

$ ssh kinneko3@TGT01 -p80
ssh_exchange_identification: Connection closed by remote host

追加した設定のどっちかが悪い感じか。


原因は、こいつだった。

on-timeout: "http";

外して再起動したらつながった。
これは、sshの場合は応答に2秒待つのがデフォルトってことか。
これを違うプロトコルに切り替えるときには、明示指定するもののようだ。
sshで接続できないのが、どういう影響になるのかはよくわからない。

注意

sshscannerなどから隠蔽できるわけではなく、ちゃんと応答する。
外部からのスキャンに耐性があるわけではないので注意。

# nmap -sV -p80 TGT01
(snip)
Host is up (0.0013s latency).
PORT   STATE SERVICE VERSION
80/tcp open  ssh     OpenSSH 6.6.1 (protocol 2.0)

というわけでバレバレ。


sshクライアント側に特殊なヘッダでも仕込んでおいて、入ってなかったらhttpに向けるみたいな対策が入るといいかも。