LoginSignup
15
15

More than 5 years have passed since last update.

Docker とWeb Proxy を使ったGate One を構築して、サーバにWeb ブラウザからSSH 接続する

Last updated at Posted at 2016-03-29

実施内容の概要

Web ブラウザからサーバにSSH 接続できるGate One を、Docker を使って構築してみます。
今回は実践することに重きを置き、Docker, Web サーバ(Apache), Gate One の基本的な機能のこと等については特に説明はしませんのでご了承ください。
主にGate One の起動と接続、Web サーバから内部のDocker へプロキシ(SSL プロキシあり/なし)及びプロキシ時の認証(SSH 接続時の認証も含めると2 段階認証)を設ける設定について実際に構築した時の手順を備忘録として記しておきます。

要件

今回Gate One をインストールする環境としては次の通りです。

  • 構成概要
    OS Fedora 23
    Docker docker-1.9.1-6.git6ec29ef.fc23.x86_64
    Docker ホストのIP アドレス 192.168.1.112

gateone docker コンテナを起動する

Gate One には既にliftoff/gateone イメージが用意されているので、を使ってGate One の簡単な使用感を確認しておきます。

dockerrun
# docker run -t --name=gateone --add-host localhost:192.168.1.112 -p 8000:8000 liftoff/gateone

以上でgateone コンテナの起動は完了です。
動作確認するために指定したホストに対してhttps 接続をしてみましょう。

適当なブラウザを開いて以下のurlにアクセス
https://192.168.112:8000/
# iptables は適宜解放しておいてください

デフォルトでGate One は自己署名された証明書を使用するので検証エラーが出るはずですが、それを無視して接続してください。
ブラウザからSSH 接続できることが確認できるはずです。

以降では、Apache を使用してweb proxy 経由でこのDocker コンテナ上のGate One を使用する環境を構築してみることにします。

内部proxy でgateone コンテナに接続する

docker コンテナの設定(SSL Proxy を使用しないで接続できるように設定)

Apache のプロキシから接続できるようにDocker コンテナの設定を変更し、再ビルドしていきます。

Gate One の設定ファイルを編集し、デフォルトでON となっているSSL/TLS 接続をOFF (disable_ssltrue)にします。
また、Gate One の接続先をデフォルとでdockerhost としておきます。
デフォルとの接続先を変更するには、command の値に記載されているコマンドの引数に--default_hosts='dockerhost' と記載しておくようにします。
このdockerhost のIP アドレスは後ほどコンテナ上のhosts として定義し、デフォルトでDocker コンテナではなく、Docker ホストに接続できるようにします。

99docker.conf
{
    "*": {
        "gateone": {
            "disable_ssl": true,
            "url_prefix": "/gateone",
            "origins": ["*"]
        },
        "terminal": { // These settings apply to the "terminal" application
            "commands": {"SSH": {"command": "/usr/local/lib/python2.7/dist-packages/gateone-1.2.0-py2.7.egg/gateone/applications/terminal/plugins/ssh/scripts/ssh_connect.py --default_host='dockerhost' -S '%SESSION_DIR%/%SESSION%/%SHORT_SOCKET%' --sshfp -a '-oUserKnownHostsFile=\\\"%USERDIR%/%USER%/.ssh/known_hosts\\\"'", "description": "Connect to hosts via SSH."}}
        }
    }
}

Dockerfile は以下のようにし、99docker.conf ファイルをDocker コンテナ上のGate One 設定ファイルディレクトリにコピーするようにします。

Dockerfile
FROM liftoff/gateone
MAINTAINER Tsutomu Nakamura

ARG DOCKER_CONF=${DOCKER_CONF:-99docker.conf}
COPY ${DOCKER_CONF} /etc/gateone/conf.d/99docker.conf

Docker イメージをビルドします。

dockerbuild
# docker build -t="proxy_gateone" .

Docker コンテナを起動します。

dockerrun
# docker run -t --name=proxy_gateone --add-host dockerhost:192.168.1.112 -p 8000:8000 proxy_gateone

Gate One 設定ファイルの設定値の上書きについて

Gate One の設定ファイルは、Gate One がインストールされたホストの/etc/gateone/conf.d ディレクトリの中に存在します。
ファイル名の形式は*.conf という形式のファイル名となっており、中身は例として次のようになっています。

10server.conf
// This is Gate One's main settings file.
{
    // "gateone" server-wide settings fall under "*"
    "*": {
        "gateone": { // These settings apply to all of Gate One
            "address": "",
            "ca_certs": null,
            "cache_dir": "/tmp/gateone_cache",
            "certificate": "/etc/gateone/ssl/certificate.pem",
            "cookie_secret": "***************************************",
            "debug": false,
            "disable_ssl": false,
            "embedded": false,
            "enable_unix_socket": false,
            "gid": "0",
            "https_redirect": false,
            "js_init": "",
            "keyfile": "/etc/gateone/ssl/keyfile.pem",
            "locale": "en_US",
            "log_file_max_size": 100000000,
            "log_file_num_backups": 10,
            "log_file_prefix": "/gateone/logs/gateone.log",
            "log_rotate_interval": 1,
            "log_rotate_mode": "size",
            "log_rotate_when": "midnight",
            "log_to_stderr": null,
            "logging": "info",
            "multiprocessing_workers": null,
            "origins": ["localhost:8000", "127.0.0.1:8000", "************:8000", "172.17.20.218:8000"],
            "pid_file": "/tmp/gateone.pid",
            "port": 8000,
            "session_dir": "/tmp/gateone",
            "session_timeout": "5d",
            "syslog_facility": "daemon",
            "uid": "0",
            "unix_socket_mode": "0600",
            "unix_socket_path": "/tmp/gateone.sock",
            "url_prefix": "/",
            "user_dir": "/gateone/users",
            "user_logs_max_age": "30d"
        }
    }
}
50terminal.conf
// This is Gate One's Terminal application settings file.
{
    // "*" means "apply to all users" or "default"
    "*": {
        "terminal": { // These settings apply to the "terminal" application
            "commands": {"SSH": {"command": "/usr/local/lib/python2.7/dist-packages/gateone-1.2.0-py2.7.egg/gateone/applications/terminal/plugins/ssh/scripts/ssh_connect.py -S '%SESSION_DIR%/%SESSION%/%SHORT_SOCKET%' --sshfp -a '-oUserKnownHostsFile=\\\"%USERDIR%/%USER%/.ssh/known_hosts\\\"'", "description": "Connect to hosts via SSH."}},
            "default_command": "SSH",
            "dtach": true,
            "enabled_filetypes": "all",
            "environment_vars": {"TERM": "xterm-256color"},
            "session_logging": true,
            "syslog_session_logging": false
        }
    }
}

今回99docker.conf というファイルを作成しましたが、上記の10server.conf ファイル内の設定値をオーバーライドするするには、ファイル名の先頭に付いている数字より大きい数値(今回は"99"としました)のファイルを用意して後から読み込まれるようにし、同じ値を再度定義してあげることでその値を上書きすることができます。
例えば先ほどの99docker.conf ファイルの例では10server.confdisable_ssl, url_prefix, origins50terminal.confcommand の値を上書きしています。

内部プロキシの設定

既にhttpd サーバを使っていて入り口を1 箇所に集約したい場合、http サーバの内部プロキシを使用してGate One コンテナへのリクエストとレスポンスを中継させるができます。

通信をプロキシするWeb サーバの要件として、Web Socket のプロキシに対応している必要があります。
Apache の場合、proxy_wstunnel_module モジュールがそれを実現するためのモジュールになるので、それがロードされていることを確認します。

proxy_wstunnel_moduleが有効になっていることの確認
# grep proxy_wstunnel_module /etc/httpd/ -r
/etc/httpd/conf.modules.d/00-proxy.conf:LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

上記のようにLoadModule でproxy_wstunnel_module が定義されていればOK です。

次に、httpd.conf にプロキシの設定を追加しますが、Docker コンテナ上のGate One にhttp, Web Socket の通信をプロキシするように設定を追加します。
今回は、/etc/httpd/conf.d/00_gateone_proxy.conf ファイルを新規に作成して次のようなproxy 設定を書き込みます。

/etc/httpd/conf.d/00_gateone_proxy.conf
<VirtualHost *:443>
    ServerName foo.example.com
    ServerAdmin webmaster@foo.example.com
    ServerSignature Off

    SSLEngine On
    SSLProxyEngine On
    SSLProtocol all -SSLv3
    SSLProxyProtocol all -SSLv3
    SSLHonorCipherOrder on
    SSLCipherSuite "ALL !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"

    SSLCertificateFile /etc/letsencrypt/live/foo.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/foo.example.com/privkey.pem

    ## Proxy authentication
    # <Proxy *://bar.example.com:8000/*>
    #     AuthType Digest
    #     AuthName "Some Digest Auth"
    #     AuthDigestProvider file
    #     AuthUserFile /etc/httpd/.htdigest
    #     Require valid-user
    # </Proxy>

    ProxyPass /gateone/ws ws://127.0.0.1:8000/gateone/ws
    ProxyPassReverse /gateone/ws ws://127.0.0.1:8000/gateone/ws
    ProxyPass /gateone http://127.0.0.1:8000/gateone
    ProxyPassReverse /gateone http://127.0.0.1:8000/gateone
</VirtualHost>

設定を追加したらhttpd をreload します。

reload
# systemctl reload httpd

reload したらweb ブラウザを開き、アクセスしてみましょう。

# https://foo.example.com/gateone

Gate One のトップページが表示され、SSH 接続できれば成功です。

GateOneProxy_0000.png

GateOneProxy_0001.png

内部proxy でgateone コンテナにSSL/TLS で接続する

先ほどのサンプルでは内部プロキシに、暗号化されていないWeb Socket, http で行っていましたが、その内部プロキシをSSL/TLS を使った方法で実施してみます。
内部プロキシの先のGate One に使用する証明書は、今回はLet's Encrypt で取得済みのものとします。
なお、今回は証明書の取得や準備については説明を割愛します。

SSL/TLS で内部プロキシを行うに当たり、環境としては以下のとおりです。

  • 内部プロキシ先のSSL/TLS 設定
    内部プロキシ先のFQDN bar.example.com 今回はApache と同じホスト上にGate One のDocker コンテナがあるものとします
    証明書ファイル /etc/letsencrypt/live/bar.example.com/fullchain.pem 中間証明書とサーバ証明書。letsencrypt で取得することを想定。Docker ホストOS 上に既にあるものを再利用
    秘密鍵ファイル /etc/letsencrypt/live/bar.example.com/privkey.pem letsencrypt で取得することを想定。ホストOS 上に既にあるものを再利用

docker コンテナの設定(SSL/TLS でListen するように設定)

Dockerfile については、先ほどの内部プロキシ設定時のDockerfile を流用します。
Gate One の設定ファイルを新規に作成(99dockerssl.conf)し、以下のようにdisable_sslfalse に変更し、certificatekeyfile を新たに定義します。

99dockerssl.conf
{
    "*": {
        "gateone": {
            "disable_ssl": false,
            "certificate": "/etc/letsencrypt/live/bar.example.com/fullchain.pem",
            "keyfile": "/etc/letsencrypt/live/bar.example.com/privkey.pem",
            "url_prefix": "/gateone",
            "origins": ["*"]
        },
        "terminal": { // These settings apply to the "terminal" application
            "commands": {"SSH": {"command": "/usr/local/lib/python2.7/dist-packages/gateone-1.2.0-py2.7.egg/gateone/applications/terminal/plugins/ssh/scripts/ssh_connect.py --default_host='dockerhost' -S '%SESSION_DIR%/%SESSION%/%SHORT_SOCKET%' --sshfp -a '-oUserKnownHostsFile=\\\"%USERDIR%/%USER%/.ssh/known_hosts\\\"'", "description": "Connect to hosts via SSH."}}
        }
    }
}

--build-arg を指定してイメージをビルドします。

dockerbuild
# docker build --build-arg DOCKER_CONF="99dockerssl.conf" -t="sslproxy_gateone" .

コンテナを起動します。

dockerrun
# docker run -t --name=gateone --add-host dockerhost:192.168.1.112 -v /etc/letsencrypt:/etc/letsencrypt -p 8000:8000 sslproxy_gateone

proxy の設定(SSL/TLS でproxy するように設定)

Apache のproxy でssl を有効とするには、SSLProxyEngine の値をOn とする必要があります。
定義例としては以下の通りです。

/etc/httpd/conf.d/00_gateone_proxy.conf
<VirtualHost *:443>
    ServerName foo.example.com
    ServerAdmin webmaster@foo.example.com
    ServerSignature Off

    SSLEngine On
    SSLProxyEngine On
    SSLProtocol all -SSLv3
    SSLProxyProtocol all -SSLv3
    SSLHonorCipherOrder on
    SSLCipherSuite "ALL !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"

    SSLCertificateFile /etc/letsencrypt/live/foo.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/foo.example.com/privkey.pem

    ## Proxy authentication
    # <Proxy *://bar.example.com:8000/*>
    #     AuthType Digest
    #     AuthName "Some Digest Auth"
    #     AuthDigestProvider file
    #     AuthUserFile /etc/httpd/.htdigest
    #     Require valid-user
    # </Proxy>

    ProxyPass /gateone/ws wss://bar.example.com:8000/gateone/ws
    ProxyPassReverse /gateone/ws wss://bar.example.com:8000/gateone/ws
    ProxyPass /gateone https://bar.example.com:8000/gateone
    ProxyPassReverse /gateone https://bar.example.com:8000/gateone
</VirtualHost>

設定を記載したら、httpd をreload します。

reload
# systemctl reload httpd

Web ブラウザを開き、先ほどと同様にGate One のページが見えることを確認してください。

Webブラウザからアクセス
# https://foo.example.com/gateone

補足: SSH ログイン時認証に公開鍵ペアを使用する

サーバが公開鍵認証を要求するように設定されている場合、Gate One のSSH クライアント側で公開鍵ペアを作成し、公開鍵を予めサーバ側に設置しておくようにしてください。
公開鍵を作成するには、SSH 接続画面から、右側のモニタアイコンをクリックし、Manage Identities をクリックします。
GateOneProxy_0002.png

SSH Identity Manager ウィンドウが出てきたら、New Identity をクリックします。
GateOneProxy_0003.png

嘉木常法入力ウィンドウが出てくるので、画面の指示に従って入力していきます。
GateOneProxy_0004.png

鍵が作成されるとSSH Identity Manager ウィンドウに戻り、右側に公開鍵情報が表示されるので、それを接続先のサーバに設置しておいてください(以降手順割愛)。

GateOneProxy_0005.png

設置したら、Gate One から接続してみて、鍵認証が通ることを確認してください。

Gate One 側の機能で実装できる認証について

今回実装したProxy 認証とSSH のログイン認証以外にGate One 側で認証機能を設けることができるようになっています。
今回設定手順については割愛しますが、kerberos, google, pam, none(認証なし) が指定できるようになっています。

origin を修正しなかった場合のエラーについて (作業備忘録)

origin の指定が明示的にあると次のようなエラーが出て、Gate One に接続できない事象が発生します。
そのため、Gate One のorigin の設定は* として設定しました。

99dockerssl.conf
{
    "*": {
        "gateone": {
            ......
            "origins": ["*"]
        },
        "terminal": { // These settings apply to the "terminal" application
            "commands": {"SSH": {"command": "......", "description": "Connect to hosts via SSH."}}
        }
    }
}
originを指定しなかった時のエラー
[E 160320 06:05:16 server:1565] Origin check failed for: https://bar.example.com
[W 160320 06:05:16 web:1946] 403 GET /gateone/ws (172.17.0.1) 8.59ms
[I 160320 06:05:18 server:1317] Settings have been modified.  Reloading from /etc/gateone/conf.d

参考

15
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
15