#0176（2025/06/22）ポートフォワード設定

# ポートフォワード設定ガイド

## 0. このガイドの目的

* **踏み台（バスティオン）サーバー A** を経由して、同一 LAN 内の **サーバー B :80** へ一時的にアクセスする方法をまとめます。
* **ローカルポートフォワード** (`ssh -L`) を中心に、実践手順、運用ノウハウ、セキュリティの勘所を網羅。
* Windows / macOS / Linux いずれのクライアントでも OpenSSH が使える前提で記載。

---

## 1. ポートフォワードとは？

* **ローカルポートフォワード**: クライアント PC のローカルポートを踏み台経由で宛先ホスト・ポートへ転送する仕組み。

  * `ssh -L <ローカルポート>:<宛先IP>:<宛先ポート> user@bastion`
    \$1

```mermaid
graph LR
    HomePC["自宅 PC"]
    Bastion["サーバー A
(Tailscale SSH)"]
    ServerB["サーバー B
社内 LAN :80"]
    HomePC -- "SSH (暗号化)" --> Bastion
    Bastion -- "TCP リレー" --> Bastion
    Bastion -- "HTTP (平文)" --> ServerB
```

---

## 2. 構成パターン別コマンド

### 2.1 シングルホスト (A 自身が宛先)

```bash
ssh -L 8080:localhost:80 user@A
```

* `http://localhost:8080` で A:80 のサービス確認。

```mermaid
graph LR
    HomePC["自宅 PC"]
    A["サーバー A :80"]
    HomePC -- "SSH (8080→80)" --> A
```

### 2.2 踏み台経由で別ホスト B へ

```bash
ssh -L 8080:192.168.10.23:80 user@A
```

* A から見た B の IP を指定。

```mermaid
graph LR
    HomePC["自宅 PC"]
    Bastion["サーバー A"]
    B["サーバー B :80"]
    HomePC -- "SSH (8080→192.168.10.23:80)" --> Bastion
    Bastion -- "HTTP" --> B
```

### 2.3 公開ポートモード (LAN 内共有)

```bash
ssh -L 0.0.0.0:8080:192.168.10.23:80 user@A
```

* **注意**: `sshd_config` で `GatewayPorts yes` が必要。安全な場面以外では非推奨。

```mermaid
graph LR
    LANClient["同一LAN内 PC"]
    HomePC["あなたの PC (0.0.0.0:8080)"]
    Bastion["サーバー A"]
    B["サーバー B :80"]
    LANClient -- "HTTP" --> HomePC
    HomePC -- "SSH (8080→B:80)" --> Bastion
    Bastion -- "HTTP" --> B
```

### 2.4 多段 (ProxyJump) 併用

```bash
ssh -J user@A user@B -L 8080:127.0.0.1:80
```

* `-J` (=ProxyJump) で多層バスティオンを一行に。

```mermaid
graph LR
    HomePC["自宅 PC"]
    A["サーバー A"]
    B["サーバー B (ターゲット) :80"]
    HomePC -- "SSH (JUMP)" --> A
    A -- "SSH トンネル" --> B
    HomePC -- "ローカル 8080" --> B
```

### 2.5 複数ポート同時フォワード

```bash
ssh -L 8080:192.168.10.23:80 -L 13306:192.168.10.23:3306 user@A
```

* Web と DB を一接続で束ねる。

```mermaid
graph LR
    HomePC["自宅 PC"]
    Bastion["サーバー A"]
    B["サーバー B"]
    HomePC -- "8080→B:80" --> Bastion
    HomePC -- "13306→B:3306" --> Bastion
    Bastion -- "HTTP" --> B
    Bastion -- "MySQL" --> B
```

---

## 3. 手順フロー (最短ルート)

1. **前提確認**

   * A から B:80 へ `curl` が通ること
   * 自宅 PC から A へ SSH (Tailscale) が通ること
2. **SSH キー認証を用意**

   * パスフレーズなしは *autossh* 併用時のみ推奨
3. **トンネル確立**

   * 例）`ssh -N -f -L 8080:192.168.10.23:80 user@A`
4. **アクセス**

   * ブラウザで `http://localhost:8080`
5. **終了**

   * `pkill -f "ssh.*8080:192.168.10.23"` または SSH プロセスを Ctrl‑C

---

## 4. 運用を楽にする Tips

* **バックグラウンド起動**: `-N -f` でターミナルを占有しない
* **自動再接続**: `autossh -M 0 ...` で回線断時に復帰
* **systemd サービス化**: 再起動後も自動で張り直す
* **ssh\_config** にエントリを登録しコマンド短縮
* **Tailscale Subnet Router**: 社内サブネット全体を広告し、ポートフォワード自体を不要に

---

## 5. セキュリティチェックリスト

* [ ] **公開鍵認証のみ**を許可 (`PasswordAuthentication no`)
* [ ] `AllowUsers` で接続許可ユーザを制限
* [ ] `GatewayPorts` は必要時のみ `yes`
* [ ] ローカルバインドポートは 1024 以上で空きを選ぶ
* [ ] トンネル使用中は **B:80** が平文 HTTP であることを認識
* [ ] 作業後にトンネルを閉じる or タイマーで自動切断

---

## 6. よくあるトラブルと対処

* **8080 が既に使用中** → `lsof -i:8080` でプロセス確認、別ポートへ変更
* **curl で接続できない** →

  * B で `ufw` / `firewalld` が 80 をブロックしていないか
  * A から B への名前解決ミスを疑う
* **SELinux が転送を阻止** → 一時的に `setenforce 0` で確認
* **トンネルが頻繁に切れる** → `ServerAliveInterval 60` + `ServerAliveCountMax 3`

---

## 7. まとめ

* `ssh -L` は **“最速 & 手軽”** な一時アクセス手段。
* 長期運用なら **autossh + systemd** で自動化。
* 社内ネットを丸ごと扱う場合は **Tailscale の Subnet Router** を検討。
* セキュリティは "開けたら閉じる" を徹底し、想定外のポート公開を防止。