0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Proxy(Squid)を経由してSFTP通信する検証をCML上で行う

Last updated at Posted at 2025-09-07

Proxy(Squid)を経由してSFTP通信する検証をCML上で行う

— 背景・HTTP CONNECTの仕組み・完全設定・検証・トラブルシュート・運用/セキュリティまで

このドキュメントで得られるもの(読む前に)

  • 所要時間の目安:構築〜検証まで 30〜60分(CMLが使える前提)
  • 習得できるスキル
    • HTTP CONNECT の基礎(SSH/SFTPを通す仕組み)
    • Squid を 22/tcp LISTEN で動かすミニマム設定
    • UFW で「Proxy 以外は 22/tcp を拒否」する実装
    • 多セグメント(3サブネット)ネットワーク設計と静的ルート
    • 失敗時のデバッグ手順ログの読み方
  • 必要な前提知識
    • Linux 基本操作(sudo, エディタ, systemd, journalctl)
    • ネットワーク基礎(L2/L3, デフォルトルート, 静的ルート)
    • CML の基礎操作(ノード作成・配線・コンソール接続)

なぜこの構成が必要?(背景・ユースケース)

  • 通常の SSH/SFTP が通らない現場
    多くの企業・閉域網では「外向きは HTTP/HTTPS のみ」「内部もプロキシ経由で統制」。22/tcp の直通は遮断されやすい。
  • HTTP CONNECT で解決
    CONNECT は任意 TCP のトンネルをプロキシ経由で張るメソッド。プロキシが 22/tcp を許可すれば SSH/SFTP を通せる
  • ユースケース
    • 直結禁止・プロキシ経由のみ許可のネットワークでの SFTP
    • 監査可能な経路(プロキシのアクセスログに残す)
    • 経路制御・あとからの追跡(誰が/いつ/どこへ)

HTTP CONNECT の要点(なぜ SSH/SFTP が通る?)

  • CONNECT <host>:<port> HTTP/1.1 をプロキシへ → プロキシが宛先に TCP 接続 → 以後は生バイトストリームを中継
  • SSH はアプリ層で暗号化済み → プロキシはL4中継のみ(中身は見えない)
  • 一般の HTTP 代理取得(GET/POST)と違い、TCP パイプを作るのが CONNECT の本質

環境・前提条件

  • Cisco Modeling Labs (CML):仮想ルータ/VMを配線して実験できるラボ環境。リンク状態が可視化され再現性が高い。
  • cloud-config(cloud-init):VM初回起動でネットワーク/ユーザ設定を自動適用。本記事では ens2=DHCP(外)ens3=固定(内)+静的ルート を配布。
  • Ubuntu VM:Squid / OpenSSH / UFW / netcat など標準パッケージが豊富で再現しやすい。

CML実装構成

topology.png

CML上の実際の構成:各VMはunmanaged-switchで外向き通信、CSRで3セグメントに分離

CMLを活用した検証観点

検証項目の体系化

この構成では以下の観点で検証を行います:

機能検証

  • SFTP接続の成功/失敗
  • ファイル転送の完了性
  • 認証・暗号化の正常動作

セキュリティ検証

  • 直接接続の遮断確認
  • プロキシ経由の強制確認
  • アクセスログの記録確認

パフォーマンス検証

  • 転送速度の測定
  • 同時接続数の上限確認
  • リソース使用量の監視

CMLを活用した検証手法

CMLの可視化機能活用

  • トポロジ図:リアルタイムでリンク状態を確認
  • ライン品質表示:帯域使用率、パケット廃棄率の監視
  • ノード状態監視:CPU、メモリ使用率のリアルタイム表示

パケット解析(CML統合Wireshark)

# CML Web UI から直接 Wireshark を起動してリンクをキャプチャ
# 1. CMLでリンクを右クリック → "Packet Capture"
# 2. Wiresharkが自動起動してパケットキャプチャ開始
# 3. HTTP CONNECT の流れを詳細に確認可能

CLI での詳細解析

# Proxy で:CONNECT リクエストの詳細確認
sudo tcpdump -ni ens3 -A -s0 'tcp port 22 and host 192.168.2.1'
# "CONNECT 192.168.4.1:22 HTTP/1.1" が確認できる

# To で:SSH ハンドシェイクの確認  
sudo tcpdump -ni ens3 -X -s0 'tcp port 22 and src 192.168.3.1'
# SSH-2.0 バナー交換が確認できる

検証用スクリプト

# パフォーマンス測定
echo "=== SFTP転送性能測定 ==="
fallocate -l 10M ~/tmp/test10M
time sftp -o "ProxyCommand=nc -X connect -x 192.168.3.1:22 %h %p" sftpuser@192.168.4.1 <<'EOF'
put ~/tmp/test10M upload/
bye
EOF

# 同時接続テスト
echo "=== 同時接続テスト ==="
for i in {1..5}; do
    (echo "接続${i}" | sftp -o "ProxyCommand=nc -X connect -x 192.168.3.1:22 %h %p" sftpuser@192.168.4.1) &
done
wait

IP 割り当て(早見表)

ノード IF 設定 備考
From ens2 DHCP (ext-conn) default route、IPは環境により変動
ens3 192.168.2.1/24 3/4 宛は 192.168.2.254
Proxy ens2 DHCP (ext-conn) default route、IPは環境により変動
ens3 192.168.3.1/24 2/4 宛は 192.168.3.254、Squid:22
To ens2 DHCP (ext-conn) default route、IPは環境により変動
ens3 192.168.4.1/24 2/3 宛は 192.168.4.254、UFW: allow-from 192.168.3.1
csr1000v-0 G3 192.168.2.254/24 From側セグメント
G4 192.168.3.254/24 Proxy側セグメント
G5 192.168.4.254/24 To側セグメント

完全版:設定ファイル & コマンド(コピペOK

1) cloud-config(各VM:起動時に IP/ルートを確定)

From(ens2=DHCP 外、ens3=192.168.2.1 内)

#cloud-config
hostname: From
manage_etc_hosts: true
system_info: { default_user: { name: cisco } }
password: cisco
chpasswd: { expire: false }
ssh_pwauth: true
timezone: Asia/Tokyo
locale: ja_JP.utf8
write_files:
- path: /etc/netplan/50-cloud-init.yaml
  content: |
    network:
      version: 2
      renderer: networkd
      ethernets:
        ens2:
          dhcp4: true
          dhcp4-overrides: { use-routes: true, use-dns: true }
        ens3:
          dhcp4: false
          addresses: [192.168.2.1/24]
          routes:
            - to: 192.168.3.0/24
              via: 192.168.2.254
            - to: 192.168.4.0/24
              via: 192.168.2.254
runcmd: [ "netplan apply" ]

Proxy(ens2=DHCP 外、ens3=192.168.3.1 内)

#cloud-config
hostname: Proxy
manage_etc_hosts: true
system_info: { default_user: { name: cisco } }
password: cisco
chpasswd: { expire: false }
ssh_pwauth: true
timezone: Asia/Tokyo
locale: ja_JP.utf8
write_files:
- path: /etc/netplan/50-cloud-init.yaml
  content: |
    network:
      version: 2
      renderer: networkd
      ethernets:
        ens2:
          dhcp4: true
          dhcp4-overrides: { use-routes: true }
        ens3:
          dhcp4: false
          addresses: [192.168.3.1/24]
          routes:
            - to: 192.168.2.0/24
              via: 192.168.3.254
            - to: 192.168.4.0/24
              via: 192.168.3.254
runcmd: [ "netplan apply" ]

To(ens2=DHCP 外、ens3=192.168.4.1 内)

#cloud-config
hostname: To
manage_etc_hosts: true
system_info: { default_user: { name: cisco } }
password: cisco
chpasswd: { expire: false }
ssh_pwauth: true
timezone: Asia/Tokyo
locale: ja_JP.utf8
write_files:
- path: /etc/netplan/50-cloud-init.yaml
  content: |
    network:
      version: 2
      renderer: networkd
      ethernets:
        ens2:
          dhcp4: true
          dhcp4-overrides: { use-routes: true }
        ens3:
          dhcp4: false
          addresses: [192.168.4.1/24]
          routes:
            - to: 192.168.2.0/24
              via: 192.168.4.254
            - to: 192.168.3.0/24
              via: 192.168.4.254
runcmd: [ "netplan apply" ]

成功チェック(各VM共通)

ip -br a | egrep 'ens2|ens3'
ip r | head -n 6
# 期待例:
# default は ens2(DHCP) 由来、2/3/4 宛は ens3 → CSR(.254)

2) CSR1000v(基本 L3)

conf t
interface g3
 description to From
 ip address 192.168.2.254 255.255.255.0
 no shutdown
interface g4
 description to Proxy
 ip address 192.168.3.254 255.255.255.0
 no shutdown
interface g1
 description to To
 ip address 192.168.4.254 255.255.255.0
 no shutdown
end
wr
show ip interface brief

期待出力(抜粋)

Gi3 192.168.2.254 up/up
Gi4 192.168.3.254 up/up
Gi1 192.168.4.254 up/up

3) To(SFTPサーバ)+ UFW(Proxy 以外は拒否

sudo apt update
sudo apt install -y openssh-server
sudo systemctl enable --now ssh

sudo adduser sftpuser
sudo -u sftpuser mkdir -p /home/sftpuser/upload
sudo chown -R sftpuser:sftpuser /home/sftpuser

# UFW:Proxy(192.168.3.1) からの 22/tcp のみ許可
sudo ufw --force reset
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from 192.168.3.1 to any port 22 proto tcp
sudo ufw logging on
sudo ufw enable
sudo ufw status verbose

期待出力(抜粋)

Status: active
To                         Action      From
22/tcp                     ALLOW IN    192.168.3.1

4) Proxy(Squid を 22/tcp で LISTEN

Ubuntu は ssh.socket が 22 を掴んでいることがあるため、sshd を別ポート(例:2222) に移します。

sudo systemctl stop ssh.socket
sudo systemctl disable ssh.socket
sudo sed -i 's/^#\?Port .*/Port 2222/' /etc/ssh/sshd_config
sudo systemctl enable --now ssh.service
sudo ss -lntp | egrep ':22|:2222'   # 22 は空、2222 で sshd LISTEN

Squid のインストール & 完全設定

sudo apt install -y squid netcat-openbsd
sudo cp /etc/squid/squid.conf /etc/squid/squid.conf.bak
sudo tee /etc/squid/squid.conf >/dev/null <<'CONF'
# === Squid on 22/tcp (bind to Proxy's inside IP) ===
http_port 192.168.3.1:22
visible_hostname proxy

# Clients allowed to use this proxy
acl fromnet src 192.168.2.0/24

# Allowed CONNECT destination/port (strictly SSH only)
acl to_ssh  dst 192.168.4.1/32
acl SSH_ports port 22
acl CONNECT method CONNECT

# Security: disallow CONNECT except 22
http_access deny CONNECT !SSH_ports

# Allow SFTP via CONNECT from "fromnet" to "to_ssh"
http_access allow CONNECT to_ssh fromnet

# Default deny (must be last)
http_access deny all

# IPv6環境のハマり回避
dns_v4_first on
CONF

sudo systemctl restart squid
sudo ss -lntp | egrep ':22|:3128'   # 192.168.3.1:22 を squid がLISTEN

期待出力(例)

LISTEN ... 192.168.3.1:22 ... users:(("squid",pid=...,fd=...))
LISTEN ... 0.0.0.0:2222 ... users:(("sshd",pid=...,fd=...))

代替:sshd を 22 のままにしたい場合、iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 22 -s 192.168.2.0/24 -j REDIRECT --to-ports 312822→3128 転送も可。

5) 検証(CLI)

CONNECT トンネルのバナー確認(From)

nc -X connect -x 192.168.3.1:22 192.168.4.1 22
# "SSH-2.0-OpenSSH_..." が見えればOK(Ctrl+C)

SFTP 転送(From→Proxy:22→To:22)

mkdir -p ~/tmp; date > ~/tmp/from-test.txt
sftp -o "ProxyCommand=nc -X connect -x 192.168.3.1:22 %h %p" sftpuser@192.168.4.1 <<'EOF'
mkdir -p upload
put ~/tmp/from-test.txt upload/
ls -l upload
bye
EOF

証跡(ログ)

# Proxy
sudo grep "CONNECT 192.168.4.1:22" /var/log/squid/access.log | tail -n1
# To
sudo journalctl -u ssh --since "10 min ago" | grep Accepted | tail -n1
# 直結の反証(失敗ログ)
sudo tail -n1 /var/log/ufw.log

Windows クライアント(WinSCP)の設定

目的:WinSCP から HTTP CONNECTProxy(192.168.3.1:22) 経由 → To(192.168.4.1:22) へ SFTP 接続。

手順(GUI)

  1. WinSCP 起動 → New Site
  2. Session
    • File protocolSFTP
    • Host name192.168.4.1(To)
    • Port22
    • User namesftpuser
  3. Advanced → Connection → Proxy
    • Proxy typeHTTP
    • Proxy hostname192.168.3.1(Proxy)
    • Port22(Squid を 22 で LISTEN)
    • 認証:未設定(Squid 側で認証有効なら入力)
  4. OK → Save(任意) → Login(初回はホスト鍵確認 → Yes)

セッションログ(抜粋例)

Connecting to proxy...
HTTP proxy CONNECT 192.168.4.1:22
Proxy: 200 Connection established
Server version: SSH-2.0-OpenSSH_9.x

トラブルシュート(実例ベース)

症状 原因 対処
Proxy error: 403 Forbidden Squid の ACL 順序/範囲ミス http_access allow CONNECT to_ssh fromnetdeny all より前へ/IP範囲を実網に合わせる
Proxy error: 503 Service Unavailable Proxy→To:22 到達不可 Proxy で nc -vz 192.168.4.1 22/To の UFW(Proxy のみ許可)/CSR の配線とルート
Temporary failure in name resolution DNS 未設定 or IPv6影響 ens2 側の DNS(DHCP配布 or nameservers)/apt -o Acquire::ForceIPv4=true update
nc: invalid option -- X BusyBox 版 nc netcat-openbsdncat を導入
Squid が 22 で LISTEN しない ssh.socket が 22 を掴んでる systemctl stop/disable ssh.socketPort 2222 に変更 → squid 再起動

診断ステップ(順番が重要)

  1. リンク:CML でリンク up(緑)
  2. ルート(各VM):ip -br a / ip r → default=ens2(DHCP) / 2-4 宛=ens3→CSR
  3. Proxy→ToProxy$ nc -vz 192.168.4.1 22
  4. CONNECTFrom$ nc -X connect -x 192.168.3.1:22 192.168.4.1 22
  5. ログ/var/log/squid/access.log / journalctl -u ssh / /var/log/ufw.log

実運用への橋渡し

複数クライアント対応

# 複数のクライアントサブネットを許可する場合
acl fromnet src 192.168.2.0/24 192.168.10.0/24
# 特定ホストのみ許可する場合  
acl fromnet src 192.168.2.1/32 192.168.2.10/32

基本的な認証追加

# 簡易Basic認証の追加(検証レベル)
sudo apt install -y apache2-utils
sudo htpasswd -c /etc/squid/passwords testuser
sudo chown proxy:proxy /etc/squid/passwords

# squid.conf に追加
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwords
acl authenticated proxy_auth REQUIRED
http_access allow CONNECT to_ssh fromnet authenticated

関連技術への言及

  • 他プロキシソフトウェアとの比較
    • Squid:フォワードプロキシ用途に強く、ACL とログが豊富(本検証で使用)
    • Nginx:HTTPプロキシとして軽量だが、CONNECTの細かい制御は限定的
  • 検証環境の発展
    • EVE-NG/GNS3:類似のネットワーク仮想化プラットフォームでの応用
    • Docker/Podman:コンテナ環境でのSquidプロキシ検証

重要な注意(まとめ)

⚠️ ACL順序が重要http_access allow CONNECT ... は必ず deny all の前に記述
⚠️ ポート競合回避ssh.socket が 22 を掴んでいると Squid は LISTEN できない
⚠️ 検証ログの確認squid access.log / ssh journal / ufw.log で動作を確認
⚠️ セキュリティ境界:To の UFW は「Proxy のみ許可」を維持して直接接続を遮断

検証完了の確認

# CONNECT の確立(SSH バナーが出れば成功)
nc -X connect -x 192.168.3.1:22 192.168.4.1 22

# ファイル転送テスト
mkdir -p ~/tmp; date > ~/tmp/test-file.txt
sftp -o "ProxyCommand=nc -X connect -x 192.168.3.1:22 %h %p" sftpuser@192.168.4.1 <<'EOF'
mkdir -p upload
put ~/tmp/test-file.txt upload/
ls -l upload
bye
EOF

# 検証ログの確認
echo "=== Proxy ログ ==="
sudo grep "CONNECT 192.168.4.1:22" /var/log/squid/access.log | tail -n1
echo "=== SSH 接続ログ ==="
sudo journalctl -u ssh --since "10 min ago" | grep "Accepted" | tail -n1
echo "=== 直接接続拒否ログ ==="
sudo tail -n1 /var/log/ufw.log

付録:WinSCP 設定(Windowsクライアント)

  • File protocol:SFTP / Host name192.168.4.1 / Port22 / Usersftpuser
  • Proxy type:HTTP / Proxy hostname192.168.3.1 / Port22
  • ログを有効化(Preferences → Logging, Debug 1 以上)→
    HTTP proxy CONNECT 192.168.4.1:22200 Connection establishedSSH-2.0-... が並べば成功。
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?