hana_shinのLinux技術ブログ

Linuxの技術情報を掲載しています。特にネットワークをメインに掲載していきます。

sshポートフォワーディングの使い方



1 ssh ポートフォワーディングとは?

暗号化機能を備えていないアプリケーションの通信をsshが間に入って中継することで、暗号化を行うことができます。

具体的には以下のようになります。
1. アプリXがポートX宛てにデータを送信する
2. ポートXでListen(受信データ待ち)しているsshにデータが届けられる
3. sshからsshdにデータを送信する。このとき、クライアントでデータを暗号化する。
4. サーバは受信したデータを復号する
5. 復号したデータをsshdが受信する
6. sshdがポートYでListenしているアプリYにデータを転送する

   client(ローカル)                               server(リモート)
+----------------------+                      +---------------------+
|                      |                      |                     |
|                      |                      |                     |
|                      |                      |        アプリY      |
|                      |                      |          A          |
|                      |                      |          |          |
|アプリX ---> ポート(X)|                      |       ポート(Y)     |
|              |       |                      |          A          |
|              V       |                      |          |          |
|              ssh ----|----(暗号化データ)----|--------> sshd       |
|                      |                      |                     |
|                      |                      |                     |
+----------------------+                      +---------------------+

2 検証環境

2.1 ネットワーク構成

サーバとクライアントの2台構成です。図中のeth0はNICの名前です。

                           192.168.122.0/24
client(eth0) ------------------------------------------(eth0) server
        .181                                           .216

2.2 版数

CentOS版数は、サーバ、クライアントともに下記版数です。

[root@agent ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

カーネル版数は以下のとおりです。

[root@agent ~]# uname -r
3.10.0-1160.el7.x86_64

sshの版数は以下のとおりです。

[root@server ~]# ssh -V
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips  26 Jan 2017

3 ポートフォワーディングの書式

ポートフォワーディングは、以下の方法があります。書式は次のとおりです。

  • ローカルからリモートへのポートフォワーディング(-L)
ssh -L 転送元ポート番号:転送先ホスト:転送元ポート番号 sshサーバ
  • リモートからローカルへのポートフォワーディング(-R)
ssh -R 転送元ポート番号:転送先ホスト:転送元ポート番号 sshサーバ

4 ローカルからリモートへのポートフォワーディング

ここでは、ローカルからリモートへのポートフォワーディングを試してみます。

4.1 接続手順

サーバでncコマンドを実行します。ncプロセスが11111番ポートでListenするようにします。なお、ncコマンドのインストール方法、使い方は、ncコマンドの使い方(ネットワーク実験の幅が広がるなぁ~) - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# nc -kl 11111

サーバでターミナルをもう1つ開きます。そして、lsofコマンドを実行します。ncプロセスがTCPの11111番ポートでListenしていることがわかります。なお、lsofコマンドのインストール方法、使い方はlsofコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# lsof -c nc -a -i -a -nP
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nc      1810 root    3u  IPv6  33827      0t0  TCP *:11111 (LISTEN)
nc      1810 root    4u  IPv4  33828      0t0  TCP *:11111 (LISTEN)

クライアントの22222番ポートへのデータ送信をサーバの11111番ポートに転送する設定をします。

[root@client ~]# ssh -L 22222:192.168.122.216:11111 192.168.122.216
root@192.168.122.216's password:
Permission denied, please try again.
root@192.168.122.216's password:
Last failed login: Wed Apr 13 19:20:07 JST 2022 from client on ssh:notty
There was 1 failed login attempt since the last successful login.
Last login: Wed Apr 13 19:15:29 2022 from client
[root@server ~]#

このとき、クライアントでlsofコマンドを実行します。sshTCPの22222番ポートでListenしていることがわかります。

[root@client ~]# lsof -i -a -i:22222 -Pn
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ssh     1704 root    4u  IPv6  36501      0t0  TCP [::1]:22222 (LISTEN)
ssh     1704 root    5u  IPv4  36502      0t0  TCP 127.0.0.1:22222 (LISTEN)

クライアントでncコマンドを実行します。

[root@client ~]# nc localhost 22222
12345

このとき、クライアントでlsofコマンドを実行します。ncコマンドは、sshがListenしているTCPの22222番ポートにTCPコネクションを確立していることがわかります。

[root@client ~]# lsof -c nc -a -i -a -nP
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nc      1739 root    3u  IPv6  36556      0t0  TCP [::1]:40726->[::1]:22222 (ESTABLISHED)

次に、クライアントで"12345"と入力します。

[root@client ~]# nc localhost 22222
12345

サーバでncコマンドの実行結果を確認します。クライアントで入力した文字列が表示されることがわかります。

[root@server ~]# nc -kl 11111
12345

4.2 ポートフォワーディング中の状態

ポートフォワーディング中は、以下のようになっています。()内はポート番号を表します。

               client                                                 server
+-----------------------------------------+    +-----------------------------------------+
|                                         |    |                                         |
|     nc                     ssh          |    |        sshd                     nc      |
| +---------+       +------------------+  |    |  +------------------+       +---------+ |
| |         |       |                  |  |    |  |                  |       |         | |
| | (40726) |       | (22222)  (xxxxx) |  |    |  | (22)     (YYYYY) |       | (11111) | |
| +---------+       +------------------+  |    |  +------------------+       +---------+ |
|   A  |                 |        |       |    |     |          |                |       |
|   |  |                 |        |       |    |     |          |                |       |
|   |  |                 |        |       |    |     |          |                |       |
|   |  +--- localhost ---+        |       |    |     | +--------+                |       |
|   |      (127.0.0.1)            |       |    |     | |+------------------------+       |
|   |                             |       |    |     | ||                                |
|   |                             |       |    |     | ||                                |
+---|-------------------------- (eth0) ---+    +-- (eth0) -------------------------------+
    |                       .181  |                  |  .216
    |                             |                  |
    V                             +------------------+
   端末                             192.168.122.0/24

4.3 送信データの確認

ポートフォワーディングのとき、送信データが暗号化されているかどうかを確認してみます。ポートフォワーディングを使用すると送信データが暗号化されますが、使用しないと暗号化されないことを確認します。

4.3.1 ポートフォワーディングを使用しない場合

サーバで firewall-cmdコマンドを実行します。ncプロセスがListenするTCPの11111番ポートを解放します。なお、 firewall-cmdコマンドの使い方は、firewall-cmdの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# firewall-cmd --add-port=11111/tcp
success

ポートの状態を確認します。TCPの11111番ポートが解放されたことがわかります。

[root@server ~]# firewall-cmd --list-ports
11111/tcp

クライアントでtcpdumpコマンドを実行します。なお、tcpdumpコマンドの使い方は、tcpdumpの使い方(基本編) - hana_shinのLinux技術ブログを参照してください。

[root@client ~]# tcpdump -i eth0 src host 192.168.122.181 and dst port 11111 -xx -n

クライアントでncコマンドを実行します。そして、クライアントからサーバの11111番ポートにデータ("111...111")を送信します。

[root@client ~]# nc 192.168.122.216 11111
1111111111111111111111111111111111111111

tcpdumpの実行結果を確認します。クライアントで入力した文字列("111...111")が暗号化されていないことがわかります。1はASCIIコードで0x31です。

[root@client ~]# tcpdump -i eth0 src host 192.168.122.181 and dst port 11111 -xx -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:19:45.956086 IP 192.168.122.181.37590 > 192.168.122.216.vce: Flags [P.], seq 10279061:10279102, ack 1430832885, win 229, options [nop,nop,TS val 4362757 ecr 4326873], length 41
        0x0000:  5254 006f b0ca 5254 00d0 e3a7 0800 4500
        0x0010:  005d b0ed 4000 4006 12cf c0a8 7ab5 c0a8
        0x0020:  7ad8 92d6 2b67 009c d895 5548 c6f5 8018
        0x0030:  00e5 772e 0000 0101 080a 0042 9205 0042
        0x0040:  05d9 3131 3131 3131 3131 3131 3131 3131
        0x0050:  3131 3131 3131 3131 3131 3131 3131 3131
        0x0060:  3131 3131 3131 3131 3131 0a
4.3.2 ポートフォワーディングを使用した場合

クライアントでtcpdumpを実行します。

[root@client ~]# tcpdump -i eth0 src host 192.168.122.181 and dst port 22 -xx -n

もう1つターミナルを開きます。そして、ncコマンドを実行して、localhostの22222番ポートに文字列("111...1111")を送信します。

[root@client ~]# nc localhost 22222
1111111111111111111111111111111111111111

tcpdumpの実行結果を確認します。クライアントで入力した文字列("111...111")は暗号化されていることがわかります。

[root@client ~]# tcpdump -i eth0 src host 192.168.122.181 and dst port 22 -xx -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:10:25.072515 IP 192.168.122.181.52946 > 192.168.122.216.ssh: Flags [P.], seq 777051684:777051760, ack 3185009407, win 309, options [nop,nop,TS val 3801873 ecr 3713766], length 76
        0x0000:  5254 006f b0ca 5254 00d0 e3a7 0800 4510
        0x0010:  0080 2e56 4000 4006 9533 c0a8 7ab5 c0a8
        0x0020:  7ad8 ced2 0016 2e50 de24 bdd7 62ff 8018
        0x0030:  0135 7751 0000 0101 080a 003a 0311 0038
        0x0040:  aae6 ad38 3b20 9e12 7e80 604b 86fd ecd2
        0x0050:  9b4d 9690 9737 9dc8 64c2 f008 1258 af14
        0x0060:  c43b c994 8a10 fd86 59cd 87b5 434e 7cc4
        0x0070:  4993 9295 63cb b450 a8c3 c4db 20ab b8f0
        0x0080:  5820 fbbb 05bb cc49 db3a 6e96 034b

Z 参考情報

私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ