SSD Nodes Learn 🎉 VPS $5.50/月〜
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-21

CGNATをVPSのリバーストンネルで回避する方法

CGNATでポート転送できない理由を確認し、安価なVPSにfrpを設定します。自宅から外向きにトンネルを接続し、公開側でHTTPSと実証済みの証明書を終端する手順です。

CGNAT 配下でポート転送が機能しない理由

CGNAT(キャリアグレード NAT)配下では、ルーターの WAN アドレスが他の契約者と共有されます。そのため、利用者専用のパブリック IP アドレスがなく、転送先となるポートもありません。リバーストンネルを使えば解決できます。安価な VPS がパブリック IP アドレスを保持し、自宅のマシンが VPS へ外向きに接続します。外部からのリクエストは、自宅のマシンがすでに確立した接続を通って戻ります。既存のハードウェアはそのまま使えます。ISP が提供しない唯一のもの、つまりルーティング可能なアドレスだけをレンタルします。

以下の各コマンドには、実行するマシンを明記しています。必要なマシンは 2 台です。パブリック IP アドレスを持つ VPS と、アクセス対象のサービスを実行する自宅のマシンです。

実際にCGNATの背後にいるか確認する方法

ルーターの管理画面を開き、表示されているWANアドレスを確認します。次に、インターネット側から見えるアドレスを調べます。

# on the home box
curl -4 -s https://ifconfig.me; echo

2つのアドレスが一致する場合は、パブリックIPを使用しています。この手順は必要ありません。ポートを転送して、読み進める必要はありません。ルーターのWANアドレスが100.64.0.0/10の範囲にある場合は、CGNATの背後にいます。この範囲はRFC 6598で定義された共有アドレス空間で、まさにこの用途のために予約されています。ISPによっては、WAN側に10.0.0.0/8を割り当てることもあります。表示が異なるだけで、状況は同じです。

何かをレンタルする前に、1点確認してください。CGNATを使用するISPの多くは、実際のIPv6プレフィックスを割り当てます。自宅の機器にグローバルIPv6アドレスがある場合は、そのアドレスのファイアウォールを開放し、トンネルを完全に省略できます。ただし、訪問者がIPv4のみのネットワークを使用している場合は機能しません。そのため、最終的にここへ行き着く人が多くなります。

VPS のリバーストンネルが内側から外側へ発信して動作する仕組み

CGNAT と一般的なホームルーターは、どちらも外部から開始される着信接続を遮断します。企業のファイアウォールも同様です。一方、外向きの接続は遮断しません。ブラウザーや更新クライアントが常に行っている通信だからです。NAT 装置は外向きの TCP 接続を検出すると、その接続のマッピングを作成し、同じ接続上の戻りの通信を許可します。外部から自宅のサーバーへの接続を開始することはできません。そのため、自宅のサーバーが接続を開始し、トンネルが同じ接続を逆方向に通して通信を戻します。

仕組みはこれだけです。自宅のサーバーが 1 つのポートから VPS へ接続し、その接続を開いたまま維持します。VPS は公開リクエストを受け付け、既存の接続を通して自宅のサーバーへ転送します。自宅の IP アドレスへ到達しようとする処理は一切ないため、自宅の IP アドレスを外部に公開する必要もありません。

ここから 2 つの利点が得られます。DNS レコードは自宅ではなく、常に VPS を指します。また、公開アドレスは VPS のアドレスになります。そのため、IP ルックアップで第三者が取得できる情報は、自宅の回線ではなく、レンタルサーバーに関するものになります。

構築方法は3つあります

  1. ssh -R: 両端にすでにインストールされており、1つのサービスや一時的なデモに適しています。ダッシュボードはなく、十分な再接続処理もありません。
  2. frp: 小規模な Go サーバー(frps)と対応するクライアント(frpc)で構成されます。1つのホスト名の背後で複数のサービスを恒常的に運用する場合に適しています。このガイドでは主にこの方法を扱います。
  3. メッシュ VPN: Tailscale、または自分で運用する WireGuard サーバーです。パブリックインターネットに何かを公開するのではなく、自分が管理するデバイス同士をプライベートに接続したい場合に適しています。

管理下にあるデバイスからのプライベートアクセスが目的なら、メッシュ VPN を選択してください。Tailscale Serve と Funnelでは tailnet の外部への公開方法を説明しています。同じ VPS 上で自己ホストする WireGuard VPNでは、経路上にサードパーティの調整サーバーを置かず、同じ構成を実現できます。どちらか一方を読んで、このページの残りは飛ばしてください。以下では、誰でも読み込めるパブリック HTTPS ホスト名が必要であることを前提にします。

簡易版: 1 つのサービスに ssh -R を使う

自宅のマシンで 127.0.0.1:3000 上のアプリを実行しており、VPS への SSH アクセスがすでにあるとします。

# on the home box
ssh -N \
  -o ExitOnForwardFailure=yes \
  -o ServerAliveInterval=30 \
  -o ServerAliveCountMax=3 \
  -R 127.0.0.1:8080:127.0.0.1:3000 \
  tunnel@vps.example.com

-R 127.0.0.1:8080:127.0.0.1:3000 により、VPS の sshd は自身の 127.0.0.1:8080 で待ち受け、そこに到着した通信を自宅のマシンの 127.0.0.1:3000 へ転送します。-N はシェルを起動しない指定です。2 つの ServerAlive オプションにより、存在しなくなった接続で処理が停止せず、約 90 秒で切断を検知します。

ここが最も混乱しやすい部分です。この待ち受けはループバック上にあるため、別の場所からの curl http://vps.example.com:8080 は失敗します。sshd には GatewayPorts no があり、リモートフォワードはループバックインターフェイスだけにバインドされます。GatewayPorts yes を設定して解決しようとしてはいけません。フォワードはループバック上に残し、以下の frp の構成と同じように nginx を前段に置いてください。これにより、公開ポートは証明書付きの 443 になり、トンネル用ポートがインターネットに直接公開されることもありません。現在どのポートがどのインターフェイスで待ち受けているか不明な場合は、Linux のポートと待ち受けを確認する簡単な説明に 10 分を使う価値があります。

VPS ですでにポートが使用されている場合、ssh は次のように表示します。ExitOnForwardFailure=yes を指定すると、動作するトンネルがないまま接続を続けずに終了します。

Warning: remote port forwarding failed for listen port 8080

通常の原因は、sshd が切断を検知しないまま以前のセッションが終了していることです。VPS の /etc/ssh/sshd_configClientAliveInterval 30ClientAliveCountMax 3 を設定し、切断されたセッションを回収してポートを解放します。コマンド全体を Restart=always と専用鍵を使う systemd unit で管理するか、autossh を使用してください。複数のサービスを扱う場合は、ここで止めて frp を使用します。

VPS に frp をタグで固定してインストールする

frp は静的な Go バイナリとしてリリースされており、Ubuntu または Debian のアーカイブには含まれていません。そのため、リリースをダウンロードして自分で検証します。バージョンを固定してください。設定形式は v0.52.0 で変更され、その後もオプション名が移動しています。古いチュートリアルでは、使用中のバイナリが認識しないキーを指定することになります。このガイドでは、2026 年 8 月 14 日に公開された v0.71.0 を使用します。

# on the VPS
FRP_VERSION=0.71.0
ARCH=amd64   # use arm64 if `uname -m` prints aarch64
cd /tmp
curl -fsSLO "https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_${ARCH}.tar.gz"
curl -fsSLO "https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_sha256_checksums.txt"
sha256sum --check --ignore-missing frp_sha256_checksums.txt

sha256sum は、次の 1 行だけを出力する必要があります。

frp_0.71.0_linux_amd64.tar.gz: OK

--ignore-missing が必要なのは、チェックサムファイルに 18 個すべてのリリースアセットが含まれており、そのうち 1 個だけをダウンロードしたためです。このフラグがない場合、sha256sum は残り 17 個を missing として報告し、ゼロ以外の終了コードで終了します。問題がないにもかかわらず、検証に失敗したように見えます。

# on the VPS
tar xzf "frp_${FRP_VERSION}_linux_${ARCH}.tar.gz"
sudo install -m 755 "frp_${FRP_VERSION}_linux_${ARCH}/frps" /usr/local/bin/frps
sudo useradd --system --no-create-home --shell /usr/sbin/nologin frp
sudo install -d -m 750 -o root -g frp /etc/frp
frps --version

frps --version0.71.0 を出力します。VPS に配置するのは frps だけです。frpc は home box に配置します。両方のバイナリをすべてのホストにインストールすると、誤って自宅でトンネルサーバーを実行することになります。

VPS の設定: token、強制 TLS、loopback リスナー

まず token を生成します。これは、VPS を portscan する第三者から tunnel を守る唯一のものです。

# on the VPS
openssl rand -base64 32

その値を /etc/frp/frps.toml に書き込みます。

bindAddr = "0.0.0.0"
bindPort = 7000

# Every listener frp creates for a proxy, including the HTTP vhost, stays on loopback.
proxyBindAddr = "127.0.0.1"
vhostHTTPPort = 8080

auth.method = "token"
auth.token = "PASTE_THE_OPENSSL_OUTPUT_HERE"

transport.tls.force = true

webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "PASTE_A_SECOND_SECRET_HERE"

log.level = "info"

このうち 4 行がセキュリティを担います。1 行ずつ確認します。

auth.token はクライアント側の auth.token と一致させる必要があります。これがないと、frps は port 7000 を見つけた任意のクライアントを受け入れます。そのクライアントは、VPS と証明書を経由して、任意のサービスを公開できます。

transport.tls.force = true は、TLS(transport layer security)ではない control 接続を拒否します。v0.50.0 以降、クライアントでは TLS がデフォルトで有効です。そのため、実運用上の負担はありません。古いクライアントや独自実装のクライアントが、通知なしに平文で接続するケースも防げます。

proxyBindAddr = "127.0.0.1" は、多くのガイドが省略している行です。この設定を実行したままにしても安全なのは、この行があるためです。proxy 用に frp が開くすべての listener を loopback interface に移します。対象には HTTP vhost と、クライアントが要求する任意の remotePort が含まれます。インターネットから、これらの listener には一切接続できません。公開される入口は、443 で待ち受ける nginx だけです。その設定と制御も自分で行います。

webServer.addr = "127.0.0.1" は dashboard が public interface で待ち受けるのを防ぎます。dashboard には private service とその traffic の完全な構成が表示されます。また、保護は 1 つの HTTP basic auth password に依存しています。そのため、0.0.0.0 で公開すべきではありません。

token を全ユーザーから読み取れないように所有者を設定し、起動前に構文を確認します。

# on the VPS
sudo chown root:frp /etc/frp/frps.toml
sudo chmod 640 /etc/frp/frps.toml
sudo -u frp frps verify -c /etc/frp/frps.toml

有効なファイルでは、次のように表示されます。

frps: the configuration file /etc/frp/frps.toml syntax is ok

形式について、時間を無駄にしないための注意点があります。frp はファイル拡張子から parser を選択します。対応しているのは .toml.yaml.yml.json です。古い .ini ファイルも、legacy conversion path を通じて読み込めます。ただし、INI は非推奨です。新しい option は TOML 用としてのみドキュメント化されています。ガイドに [common] section と server_addr = x.x.x.x が出てくる場合、そのガイドは v0.52.0 より前のものです。そこに記載された key name は、インストールした binary と一致しません。

権限を持たないサービスとして frps を実行する

bindPort は 7000、vhostHTTPPort は 8080 です。どちらも 1024 より大きいため、frps が root を必要とすることはなく、CAP_NET_BIND_SERVICE も必要ありません。vhost をポート 80 に設定して nginx に受けさせない理由はこれです。

/etc/systemd/system/frps.service を作成します。

[Unit]
Description=frp reverse tunnel server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=frp
Group=frp
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
Restart=on-failure
RestartSec=5s
LimitNOFILE=65535
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true

[Install]
WantedBy=multi-user.target
# on the VPS
sudo systemctl daemon-reload
sudo systemctl enable --now frps
sudo journalctl -u frps -n 20 --no-pager

ログに両方のリスナーが表示されることを確認します。ポート番号よりもアドレスのほうが重要です。

frps tcp listen on 0.0.0.0:7000
http service listen on 127.0.0.1:8080

ProtectSystem=strict により、このサービスから見えるファイルシステム全体が読み取り専用になります。ログはデフォルトで標準出力に出力され、journald が取得するため、frps はこの設定でも動作します。log.to にファイルパスを設定すると、対応する ReadWritePaths= 行を追加するまで、サービスはそのファイルに書き込めず失敗します。そのため、デフォルトのままにしてください。

ファイアウォール: ポート範囲ではなく 1 つのポートを開く

# on the VPS
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 7000/tcp
sudo ufw enable
sudo ufw status numbered

ルールは 4 つです。そのうち 1 つは証明書の更新にのみ使用します。22 は SSH です。80 は 443 にリダイレクトし、ACME(自動証明書管理環境)のチャレンジに応答します。443 はすべてのトンネル接続されたアプリを提供します。7000 は frp の制御ポートで、クライアントが到達する必要があるポートはこれだけです。

sudo ufw allow 20000:30000/tcp のような範囲を開くよう指示するガイドは、各サービスが独自のパブリック TCP ポートを使用する別の構成を説明しています。この構成では、すべての通信が 443 に到達し、frp がホスト名に基づいてルーティングするため、そのような設定は不要です。後から本当にパブリックな TCP ポートが 1 つ必要になった場合は、proxyBindAddr0.0.0.0 に戻し、クライアントが指定したポートだけを使用できるように制限を追加します。

allowPorts = [
  { start = 20000, end = 20010 }
]
maxPortsPerClient = 5

多くのプロバイダーは、サーバー上の ufw とは別に、コントロールパネルでネットワークファイアウォールも提供しています。sudo ufw status で正しいように見えるルールを設定してもタイムアウトする場合は、通常、そちらでブロックされています。VPS に実際に必要な ufw ルールでは、このセクションが前提とするデフォルト拒否の設定を説明しています。

VPS で実証明書を使って HTTPS を終端する

home.example.com の A レコードを VPS のパブリック IP に向けます。自宅には向けません。自宅には指定先にできるアドレスがないことが問題の原因です。

# on the VPS
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx

まず、通常の port 80 ブロックで /etc/nginx/sites-available/home.example.com を作成します。certbot が処理する対象として一致する server_name が必要です。

server {
    listen 80;
    listen [::]:80;
    server_name home.example.com;
    location / { return 404; }
}
# on the VPS
sudo ln -s /etc/nginx/sites-available/home.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot certonly --nginx -d home.example.com

nginx -t は、ファイルの構文解析に成功すると nginx: configuration file /etc/nginx/nginx.conf test is successful を出力します。reload の前には毎回実行してください。reload に失敗した場合、nginx は以前の設定で動作し続けます。そのため、編集ミスが「編集が反映されなかった」ように見えます。

WebSocket の upgrade には、http レベルで 1 つの map が必要です。/etc/nginx/conf.d/upgrade.conf に配置します。

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

次に、サイトファイルを実際の設定に置き換えます。

server {
    listen 80;
    listen [::]:80;
    server_name home.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name home.example.com;

    ssl_certificate     /etc/letsencrypt/live/home.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/home.example.com/privkey.pem;

    client_max_body_size 512m;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        $connection_upgrade;
        proxy_read_timeout 3600s;
    }
}

ここで proxy_set_header Host $host; は必須です。frp の HTTP vhost は Host ヘッダーに基づいてルーティングし、クライアント設定の customDomains リストと照合します。このヘッダーを省略すると、nginx は Host: 127.0.0.1 を送信します。frp はその名前に対応するプロキシを見つけられず、訪問者にはアプリのページではなく frp の素の 404 が表示されます。nginx のリバースプロキシブロックの各行を解説では、その他のヘッダーの役割を説明しています。

# on the VPS
sudo nginx -t && sudo systemctl reload nginx
sudo certbot renew --dry-run

dry run により、誰も監視していない 90 日後にも更新が機能することを確認できます。port 80 に到達できる必要があるため、ufw のルールを設定しています。

自宅側: 権限を持たないサービスとしての frpc

自宅のマシンに frpc を、frps をインストールしたときとまったく同じ手順で導入します。バージョンとチェックサムの確認手順も同じにします。その後、同じ frp ユーザーと /etc/frp ディレクトリを作成します。/etc/frp/frpc.toml を作成します。

serverAddr = "vps.example.com"
serverPort = 7000

auth.method = "token"
auth.token = "PASTE_THE_SAME_TOKEN_HERE"

transport.tls.enable = true
loginFailExit = false

proxies = [
  { name = "home-app", type = "http", localIP = "127.0.0.1", localPort = 3000, customDomains = ["home.example.com"] }
]

このファイルでは、キーの順序が重要です。見た目の問題ではありません。TOML では、テーブルヘッダーの後にあるすべてのキーがそのテーブルに属します。そのため、serverAddr のようなトップレベル設定をプロキシのテーブルヘッダーの下に記述すると、意図せずプロキシ設定になり、frp に無視されます。上記のようにプロキシ一覧をインライン配列として記述すると、この問題を避けられます。すべてのトップレベルキーが明確にトップレベルとして扱われます。

type = "http" により、このプロキシは独自の公開 TCP ポートを確保せず、vhost リスナー経由でルーティングされます。そのため、ファイアウォールのルールは 4 つのままでした。customDomains には、nginx が Host ヘッダーで転送するホスト名を指定する必要があります。したがって、指定する値は home.example.com であり、VPS の IP アドレスではありません。

loginFailExit = false は見た目以上に重要です。デフォルト値は true であり、最初のログイン試行に失敗すると frpc が終了します。ISP への接続が確立する前に起動を完了する自宅のマシンでは、これは気付くまで停止したままのサービスになります。false に設定すると、VPS が応答するまで frpc は再試行を続けます。

/etc/systemd/system/frpc.service を作成します。

[Unit]
Description=frp reverse tunnel client
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=frp
Group=frp
ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml
Restart=always
RestartSec=10s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true

[Install]
WantedBy=multi-user.target
# on the home box
sudo chown root:frp /etc/frp/frpc.toml
sudo chmod 640 /etc/frp/frpc.toml
sudo -u frp frpc verify -c /etc/frp/frpc.toml
sudo systemctl daemon-reload
sudo systemctl enable --now frpc
sudo journalctl -u frpc -n 20 --no-pager

接続したクライアントには run id が記録されます。

login to server success, get run id [3a1f9c2b7d4e5f60]

ブラウザーで https://home.example.com を開くと、自宅の 127.0.0.1:3000 上で動作しているアプリケーションが表示されます。クライアント側の Restart=always は意図的な設定です。自宅の接続は切断されることがあるため、手動で対応しなくてもサービスが復旧します。

公開インターフェースでダッシュボードを公開しない

webServer.addr = "127.0.0.1" を使用すると、ダッシュボードは VPS 自身からの接続にのみ応答します。ポートを開放する代わりに、ローカルフォワードを使用してノート PC からアクセスします。

# on your laptop
ssh -N -L 7500:127.0.0.1:7500 you@vps.example.com

http://127.0.0.1:7500 を開き、frps.toml に記載された webServer.userwebServer.password でサインインします。このページには、接続中のすべてのクライアントと各プロキシのトラフィックカウンターが表示されます。そのため、「自宅のボックスは現在接続されているか」という問いに最も速く答えられます。ssh セッションを閉じると、ダッシュボードには再びアクセスできなくなります。

トンネルが行わないこと

この部分は 2 回読んでください。ここが被害につながる箇所だからです。トンネルによって、非公開のサービスをパブリックインターネットから到達可能にできます。トンネルは、接続してくる利用者を認証しません。https://home.example.com が解決されると、スキャナーは数日以内にそのサービスを発見します。名前を誰にも伝えていなくても同じです。Certificate Transparency ログには、証明書を発行したすべてのホスト名が記録されます。そのため、certbot が成功した時点で名前は公開されます。

公開するものには、それ自体で認証機能が必要です。レート制限を備えた適切なログイン機能がアプリにあるなら問題ありません。ログインが共有パスワード 1 つだけの場合や、ログイン機能がない場合は、VPS 上で認証プロキシを前段に配置してください。アプリの前段に配置する oauth2-proxy が一般的な選択肢です。nginx と frp の vhost の間に配置でき、トンネルの両端を変更する必要はありません。

frps.toml のトークンが保護するのはトンネルであり、アプリではありません。このトークンにより、第三者が VPS に独自のプロキシを登録することを防げます。しかし、意図的に公開したホスト名宛てに 443 番ポートへ到着するリクエストには何の効果もありません。

維持すべき習慣が 2 つあります。1 つ目は、両方のファイルを編集して両方のサービスを再起動し、トークンをローテーションすることです。トークンは自動的には期限切れになりません。2 つ目は、frp を最新の状態に保つことです。このバイナリはパブリックインターネットに面した入口です。v0.71.0 のリリースノートには、クライアントから送信された不正な値によってサーバーが panic する問題が記載されています。この種のバグは、原因を推測するのではなく、修正版を適用して解決すべきです。

障害パターンと表示される文字列

クライアントが接続できない。 journalctl -u frpcconnect to server error: に続いて繰り返し表示され、その後ダイヤルタイムアウトになります。ポート 7000 に到達する通信がありません。VPS の ufw、次にコントロールパネルのプロバイダー側ネットワークファイアウォールを確認し、getent hosts vps.example.com で名前解決できることを確認します。

トークンが正しくない。 クライアントには次のように明確に表示されます。

login to the server failed: token in login doesn't match token from configuration

トークンをもう一度コピーします。末尾の改行や、引用符で囲まれていない shell 文字列内の $ が空文字列に展開されることが、これらの原因のほとんどです。そのため、TOML ファイルでは openssl rand -base64 32 の値を引用符で囲みます。

トンネルは起動しているが、ブラウザーに単純な 404 が返る。 frpc はログイン成功を記録し、ダッシュボードにもプロキシが表示されていますが、ページはアプリのスタイルなしで 404 を返します。これは、frp にこの Host ヘッダーに対応するプロキシがないことを示します。nginx と TLS を迂回し、VPS 上で vhost に直接アクセスしてテストします。

# on the VPS
curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: home.example.com' http://127.0.0.1:8080/

このコマンドから 404 が返る場合、customDomains が正しくありません。それ以外のコードが返る場合、nginx から正しい Host がリクエストに設定されていません。

nginx から 502 が返る。 nginx は応答していますが、frp は応答していません。VPS で sudo ss -lntp | grep 8080 を実行すると、frps が 127.0.0.1:8080 で待ち受けていることを確認できます。出力が空の場合、frps が停止しているか、frps.tomlvhostHTTPPort が未設定です。

アプリがすべての訪問者をローカルとして認識する。 アプリのログに、すべてのリクエストで 127.0.0.1 が記録されます。frp は X-Forwarded-For を設定し、nginx はそこに追記するため、実際のクライアントアドレスはそのヘッダーに入っています。アプリがそのヘッダーを信頼するように設定します。アプリが IP アドレスでレート制限を行う場合は、これを省略しないでください。現状では、インターネット上のすべての訪問者が 1 つのバケットを共有することになります。

長時間のリクエストが 60 秒で切断される。 アップロードまたはストリーミング応答が途中で停止します。これはトンネルではなく、nginx のデフォルトの proxy_read_timeout です。上記のブロックでこれを 3600s に引き上げています。client_max_body_size はアップロードサイズに対応する制限で、デフォルト値は 1 MB です。これを超えるボディは 413 で拒否されます。

正常に動作していたが、ルーターの再起動後に停止する。 frpc の unit にある Restart=alwaysloginFailExit = false で対処できます。sudo systemctl is-enabled frpc で確認し、enabled が出力されることを確認します。

FAQ

CGNAT 配下にいるかどうかを確認するにはどうすればよいですか?

ルーターの管理画面に表示される WAN アドレスと、同じネットワーク内から curl -4 -s https://ifconfig.me が報告するアドレスを比較します。両者が異なり、ルーターの WAN アドレスが 100.64.0.0/10 に含まれている場合、ISP はキャリアグレード NAT を使用しています。この範囲は RFC 6598 の共有アドレス空間であり、この用途のために存在します。ISP によっては WAN 側で 10.0.0.0/8 を使用することもありますが、意味は同じです。2 つのアドレスが一致する場合はパブリック IP です。ポートを転送すれば完了です。

リバーストンネルにドメイン名は必要ですか?

ここで説明する HTTPS 構成では必要です。証明書はホスト名に対して発行されます。また、frp の HTTP vhost は Host ヘッダーに基づいてリクエストをルーティングするため、両端で合意できる名前が必要です。番号付きポートを使用する raw TCP プロキシなら、ドメインなしで VPS の IP アドレスに接続できます。ただし、その場合は証明書もホスト名ベースのルーティングもないため、1 つの公開ポートで提供できるサービスは 1 つだけです。

パブリック VPS で frp を実行しても安全ですか?

制御ポートだけを公開し、認証を有効にすれば安全です。両端で auth.token にランダムな値を設定し、サーバー側では transport.tls.force = true を設定します。次に proxyBindAddr = "127.0.0.1" を設定し、frp がプロキシ用に開くポートがインターネットに面しないようにします。ダッシュボードは webServer.addr = "127.0.0.1" に維持し、SSH のローカルフォワード経由でアクセスします。新しいリリースが出たらバイナリを更新してください。frp はパブリックアドレスで待ち受けるプロセスだからです。

ssh -R の転送ポートに誰も接続できないのはなぜですか?

sshd には GatewayPorts no が設定されているため、リモートフォワードは VPS のループバックインターフェースにだけバインドされます。VPS 自体で実行した curl は動作しますが、他の場所からの curl はタイムアウトします。正しい対処は、フォワードをループバックに残し、その前段で nginx を 443 番ポートで動作させることです。GatewayPorts yes を設定すると、証明書も TLS もない raw ポートを公開することになります。これは解決しようとしている問題より悪い状態です。

frp と Tailscale や WireGuard のようなメッシュ VPN のどちらを使うべきですか?

自分のデバイスだけがアクセスする場合は、メッシュ VPN を使用してください。何も公開されず、スキャン可能なパブリックホスト名も存在しないためです。Webhook 受信サービスや、VPN クライアントをインストールしない人と共有するページなど、任意のブラウザーから読み込めるパブリック HTTPS アドレスが必要な場合は frp を使用します。両者は 1 台の VPS 上で異なるポートを使い、それぞれ別の用途で問題なく併用できます。

#frp#cgnat#nat#tunnel#reverse-proxy