はじめに
この記事は富士通クラウドテクノロジーズ Advent Calendar 2021の24日目の記事です。
こんにちは新入社員の @u-koji です。
昨日の記事は @s_ave さんによる「Apache BenchとVegetaを使ってLiteSpeed/Nginx/Apacheを性能比較」でした。
スループットや負荷への耐性がWebサーバによって有意に異なるということを知って大変おどろきました。
使い方によって最適なWebサーバを選択できるよう、ぜひ参考にさせていただきたいです。
この記事の目標
以下の状況を想定します。
- 組織のWAN
- 外部のサーバにアクセスでは必ずプロキシを経由する
- クラウド上に構築したシステム
- クラウド上のVMへのsshには踏み台サーバを経由する
この記事では組織のWANに接続されたローカルPCから、sshを駆使してクラウド上の各種サーバにアクセスする方法を紹介します。
なおプロキシ、踏み台の設定によっては紹介した機能が制限されていることもありますのでご注意ください。
踏み台サーバにログインする
Linux/Macの場合
MacOSや多くのLinuxディストリビューションでは標準でOpenSSHクライアントがインストールされています。
OpenSSHはそれ自身でプロキシ経由でSSH接続することはできませんが、ProxyCommandオプションで外部のコマンドを呼び出すことでプロキシ経由でSSH接続が可能です。
connect-proxyコマンドとncコマンドを使って、HTTPプロキシ、SOCKS5プロキシ経由で踏み台にSSHする方法を以下に記します。
(コマンドはOS推奨のパッケージなどを利用してインストールしてください。)
# connect-proxyを使う場合
## http
ssh -o "ProxyCommand connect-proxy -H http_user@http_proxy.example.com:3128 %h %p" bation_user@bation.example.com
## socks5
ssh -o "ProxyCommand connect-proxy -S socks_user@socks_proxy.example.com:1080 %h %p" bation_user@bation.example.com
# ncを使う場合
## http
ssh -o "ProxyCommand nc -X connect -P http_user -x http_proxy.example.com:3128 %h %p" bation_user@bation.example.com
*ncコマンドを用いてSOCKS5経由でコネクションを張るには-X 5
オプション(-X
でプロトコルを選択しない場合はデフォルトでSOCKS5)を指定するとマニュアルには記載されていますが、検証環境では以下のエラーのため接続できませんでした;(求情報)
nc: authentication method negotiation failed
$HOME/.ssh/config
に以下の設定を書き込むことで、コマンドをオプションを省略することができます。
Host Bation
HostName bation.example.com
User bation_user
Port 22
ProxyCommand connect-proxy -H http_user@http_proxy.example.com:3128 %h %p
# 外部コマンドとオプションは任意のものを記載
# 公開鍵を利用したい場合はよしなにIdentityfileを記載
この例では、ssh Bation
とコマンドを入力することで踏み台サーバに接続することができます。
Windowsの場合
WindowsでProxyを経由してSSHを行いたい場合、主に以下の3つの方法があると思います。
ターミナルエミュレータを利用する
Tera TermやRloginなどのターミナルエミュレータでは、オプションを設定することでプロキシ経由で外部サーバにSSHすることができます。(説明は省きます)
WSLを利用する
WSLの任意のディストリビューションを利用して、Linux/Macの場合と同様にSSHすることができます。
Git Bash + OpenSSH
Git Bash同梱のMingw-w64にはWindowsで使えるconnectのバイナリが配布されており、これを利用してcmdからOpneSSHコマンドを利用してProxy経由でSSH接続ができます。
Git Bash(Git for Windows)をインストールして%homepath%\.ssh\config
に以下の設定をしてください。
Host Bation
HostName bation.example.com
User bation_user
Port 22
ProxyCommand C:\Program Files\Git\mingw64\bin\connect.exe -H http_user@http_proxy.example.com:3128 %h %p
# connect.exeのパスはx86の場合とAMD64の場合で異なるため事前に確認してください
# SOCKS Proxyの場合は `-S socks_user@socks_proxy.example.com:1080`
コマンドプロンプトやPowerShellでssh Bation
とすることで、踏み台サーバにログインできます。
*ちなみにMingw-w64単体にはconnect.exeは含まれておらず、Git Bashをインストールする必要がありました。
開発サーバにSSH
踏み台サーバにSSHした後に、踏み台サーバで再度sshコマンドを叩くことで開発サーバにログインすることができます。
-J(ProxyJump)オプションを利用すると、sshコマンドを2回実行する必要がなく、一発で踏み台サーバを経由して開発サーバにsshすることができます。
先程設定した.ssh/config
を利用すると、以下のコマンドでログインできます。
ssh remote_user@ -J Bation
DBへのポートフォワーディング
SSHにはポートフォワーディング機能が備わっており、これを活用することでローカルからDBにログインすることが可能です。
以下の例では.ssh/config
に記載したBationを経由し、ローカルの3306ポートをDBサーバの3306ポートにフォワーディングしています。
ssh -L 3306:192.0.2.3:3306 Bation
このコマンドを実行するとプロンプトは踏み台サーバにログインした状態になります。
プロンプトのログインを保持したまま、CLIやGUIのDBクライアントでlocalhost(127.0.0.1):3306に接続することで、DBサーバにログインできます。
mysql -h 127.0.0.1 -uuser -p
*小ネタですが、mysqlでlocalhostを指定した場合はデフォルトでUNIXソケットを利用するため、127.0.0.1としています。
SOCKSを利用したWebサーバへのアクセス
DBサーバにアクセスしたときと同様に、Webサーバの80番ポートをローカルの8080番ポートなどにフォワーディングすることで、ローカルからWebサーバにアクセスすることができます。
しかし複数のWebサーバが立ち上がっている場合などはポートの割当が大変になってきます。
sshの-D
オプションを利用することで、sshをSOCKS5プロキシとして動作させることができ、プライベートLAN上のサーバへのアクセスが楽になります。
ssh -D 1080 Bation
ポートフォワーディングの時と同様にプロンプトは踏み台サーバにログインした状態になります。
その間はlocalhost:1080が踏み台へのSOCKS5プロキシとして動作します。
curl --proxy socks5://localhost:1080 192.0.2.4
またプロキシの設定をすることで、WebブラウザからもプライベートLAN上に構築したWebコンテンツの閲覧が可能になります。
終わりに
今回はSSHを活用して、幾多の試練(プロキシや踏み台)を乗り越え幸せな開発環境を構築する方法をご紹介しました。
みなさまの素敵なSSHライフに貢献できれば幸いです。
ここまで続いてきたアドベントカレンダーもついに明日で最後となります!
明日は @ConHumi さんの「FJCT エンジニアタスクフォース 2021 レポート」です。
それではみなさん、よいクリスマスを!
おまけ
今回検証環境はDockerを利用して構築しました。
おそらくいないと思いますが、必要な人がいましたらご利用ください。
ソース
version: '3'
services:
socks5:
image: serjs/go-socks5-proxy
ports:
- "1080:1080"
environment:
- PROXY_USER=socks_user
- PROXY_PASSWORD=socks_password
networks:
- net1
http-proxy:
image: babim/squid
ports:
- "3128:3128"
environment:
- AUTH=true
- USERNAME=http_user
- PASSWORD=http_password
networks:
- net1
bation_sshd:
build:
context: ./sshd
dockerfile: ./Dockerfile
args:
- USER=bation_user
- PASSWORD=bation_password
networks:
- net1
- net2
remote_sshd:
build:
context: ./sshd
dockerfile: ./Dockerfile
args:
- USER=remote_user
- PASSWORD=remote_password
networks:
- net2
web:
image: nginx
networks:
- net2
db:
image: mariadb
environment:
MARIADB_ROOT_PASSWORD: root_password
MARIADB_USER: user
MARIADB_PASSWORD: user_password
networks:
- net2
networks:
net1:
net2:
sshdのDokcerfileはDockerのドキュメントとほぼ同じです。
FROM ubuntu:14.04
ARG USER
ARG PASSWORD
RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN useradd $USER
RUN echo ${USER}:${PASSWORD} | chpasswd
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]