Carpe Diem

備忘録

sshポートフォワーディング

概要

sshポートフォワーディングの仕組みを説明します。

簡単に言うと、直接アクセスできないサーバ(Target)に対し、何かしら踏み台サーバ(Remote)を経由させることでまるで直接アクセスできるようにする仕組みです。

f:id:quoll00:20200822112146p:plain

その際に踏み台サーバに対しては上図のようにsshプロトコルを使います。

環境

  • Ubuntu 18.04
  • OpenSSH 7.6p1
  • Redis 4.0.9

構成

以下のような構成を想定します。

name ip 説明
local 192.168.1.10 ローカルマシン
remote 192.168.1.20
172.16.1.10
targetへの踏み台とするサーバ。
localからアクセス可能
target 172.16.1.20 アクセスしたいDBを持つ。
remoteからのみアクセス可能

DBはインストールが楽なRedisを使います。

Vagrantで以下のファイルで構築します。

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/bionic64"

  config.vm.define :local do |local|
    local.vm.network "private_network", type: "dhcp"
    local.vm.network "private_network", ip: "192.168.1.10", virtualbox__intnet: "NW1"
  end

  config.vm.define :remote do |remote|
    remote.vm.network "private_network", type: "dhcp"
    remote.vm.network "private_network", ip: "192.168.1.20", virtualbox__intnet: "NW1"
    remote.vm.network "private_network", ip: "172.16.1.10", virtualbox__intnet: "NW2"
  end

  config.vm.define :target do |target|
    target.vm.network "private_network", type: "dhcp"
    target.vm.network "private_network", ip: "172.16.1.20", virtualbox__intnet: "NW2"
  end
end

検証

ローカルフォワーディング

ローカルの6379ポートにアクセスすると、ターゲットの6379ポートにアクセスできるようにするには以下のように設定します。

$ ssh -NL 6379:target:6379 remote

先程の構成図でいうと

$ ssh -NL 6379:172.16.1.20:6379 192.168.1.20

と書きます1フォワグラウンド2でリスナーが起動します。停止したいときはCtrl-Cしてください。

別ターミナルでローカルの6379ポートを見てみると

$ sudo lsof -i :6379
COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ssh     14157 vagrant    4u  IPv6  45866      0t0  TCP ip6-localhost:6379 (LISTEN)
ssh     14157 vagrant    5u  IPv4  45867      0t0  TCP localhost:6379 (LISTEN)

このようにsshがLISTENしていることが確認できます。

redis-cliでローカルアクセスしてみると

$ redis-cli
127.0.0.1:6379>

ターゲットのredisサーバへと繋がります。

コネクションの確認

コネクションがどうなって転送されているのかを確認します。

localのコネクション

netstatで見るとこうなります。

$ sudo netstat -untap | grep -e redis -e ssh
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      1844/ssh
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      959/sshd
tcp        0      0 127.0.0.1:6379          127.0.0.1:50976         ESTABLISHED 1844/ssh
tcp        0      0 192.168.1.10:51758      192.168.1.20:22         ESTABLISHED 1844/ssh
tcp        0      0 10.0.2.15:22            10.0.2.2:57560          ESTABLISHED 1930/sshd: vagrant
tcp        0      0 10.0.2.15:22            10.0.2.2:57420          ESTABLISHED 1749/sshd: vagrant
tcp        0      0 127.0.0.1:50976         127.0.0.1:6379          ESTABLISHED 1958/redis-cli
tcp        0      0 10.0.2.15:22            10.0.2.2:57559          ESTABLISHED 1845/sshd: vagrant
tcp6       0      0 ::1:6379                :::*                    LISTEN      1844/ssh
tcp6       0      0 :::22                   :::*                    LISTEN      959/sshd

ポイントとしては以下。

  • sshがポート6379でLISTEN
  • redis-cliと↑でコネクション張ってる
  • sshでremote(192.168.1.20)のポート22に対してコネクション張ってる

remoteのコネクション

netstatで見るとこうなります。

$ sudo netstat -untap | grep ssh
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      961/sshd
tcp        0      0 172.16.1.10:43048       172.16.1.20:6379        ESTABLISHED 1858/sshd: vagrant
tcp        0      0 10.0.2.15:22            10.0.2.2:57421          ESTABLISHED 1697/sshd: vagrant
tcp        0      0 192.168.1.20:22         192.168.1.10:51758      ESTABLISHED 1791/sshd: vagrant
tcp6       0      0 :::22                   :::*                    LISTEN      961/sshd

ポイントとしては以下。

  • sshでlocal(192.168.1.10)とコネクション張ってる
  • sshがtarget(172.16.1.20)のポート6379とコネクション張ってる

targetのコネクション

netstatで見るとこうなります。

$ sudo netstat -untap | grep -e redis -e ssh
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      998/sshd
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      1100/redis-server 0
tcp        0      0 10.0.2.15:22            10.0.2.2:57422          ESTABLISHED 1814/sshd: vagrant
tcp        0      0 172.16.1.20:6379        172.16.1.10:43048       ESTABLISHED 1100/redis-server 0
tcp6       0      0 :::22                   :::*                    LISTEN      998/sshd

ポイントとしては以下。

  • redis-serverがポート6379でLISTENしてる
  • remote(172.16.1.10)からredis-serverに対してコネクション張ってる

まとめ

コネクション周りを中心にsshポートフォワーディングしてるとどういう状態になっているかを説明しました。

参考


  1. -Nオプションが無いと普通にsshを繋いだ画面になります。

  2. -fオプションを付けるとバックグラウンドで起動します。