Cloudflare で 1つの FQDN に対して Web / Non-Web ポートを両方対応する

# 目的
Cloudflare で 1つの FQDN に対して Web / Non-Web ポートを両方対応する方法について確認します。

以下のようなイメージになりますが、稀にこういう構成は存在します。

オリジンは場合によっては、別サーバーに分かれているかもしれません。

```mermaid:
%%{init: {'themeCSS': 'img {width: 48px; height:48px;}'}}%%
graph LR

FTP:::hidden
SSH:::hidden
HTTP:::hidden

subgraph Cloudflare
    FQDN[<img src='https://cf-icons.pages.dev/logo-cloud.svg' width='48' height='48'/><br>FQDN.example.com]:::transparent
end

Origin[<img src='https://cf-icons.pages.dev/server-origin.svg' width='48' height='48'/><br>Origin]:::transparent

FTP --> |FTP|FQDN
SSH --> |SSH|FQDN
HTTP --> |HTTP/HTTPS|FQDN

FQDN --> Origin

classDef hidden display: none;
classDef transparent fill-opacity:0,stroke-opacity:0;
```

# Cloudflare CDN で対応する標準 Web 通信ポート
というのも、ドキュメントにある通り、Cloudflare CDN で対応する標準 Web 通信ポートは以下のものに限られています。

https://developers.cloudflare.com/fundamentals/reference/network-ports/#network-ports-compatible-with-cloudflares-proxy

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/3bddd565-b914-36a2-649d-b9e2b118caa6.png)

# 1つの FQDN に対して Web / Non-Web ポートを両方対応するには

では、どうするかというと、任意の TCP / UDP ポートで受け付けることができる Cloudflare Spectrum という製品を使います。

例えば、 Spectrum を使えば、上記の標準ポート以外で  Web 通信を終端し、WAF を適用するといったことが可能です。

https://developers.cloudflare.com/spectrum/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/55e80b1a-8ff1-41a9-08cd-777f7c5e5e9d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/e7d0749b-1c57-7b30-5129-214f45e52f24.png)

# 参考： CDN が有効な状態で Spectrum レコード作成時のエラー
ちなみに CDN の方ですでに A / AAAA / CNAME レコードが存在する場合は、以下のエラーによって Spectrum レコードが作成できません。

CDN の方で A / AAAA / CNAME レコードがないことを確認して、Spectrum から FQDN レコードを作成するようにしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/3c774dc1-13f5-3d33-8593-e4c5cfe8cb4e.png)

# Spectrum レコードを使った構成
具体的には Spectrum を使って、以下のような構成を実現できます。

```mermaid:
%%{init: {'themeCSS': 'img {width: 48px; height:48px;}'}}%%
graph LR

FTP:::hidden
SSH:::hidden
HTTP:::hidden

subgraph Cloudflare [Cloudflare]
subgraph Spectrum
subgraph HTTPApp [HTTP/HTTPS Application]
    FQDN-HTTP[<img src='https://cf-icons.pages.dev/spectrum.svg' width='48' height='48'/><br>FQDN.example.com]:::transparent
end
subgraph TCPApp [TCP Application]
    FQDN-SSH[<img src='https://cf-icons.pages.dev/spectrum.svg' width='48' height='48'/><br>FQDN.example.com]:::transparent
end
end
subgraph CDN [CDN Pipeline]
    WAF[<img src='https://cf-icons.pages.dev/waf.svg' width='48' height='48'/><br>WAF, etc]:::transparent
end
end

Origin[<img src='https://cf-icons.pages.dev/server-origin.svg' width='48' height='48'/><br>Origin]:::transparent

SSH --> |TCP Port 22|FQDN-SSH
HTTP --> |TCP Port 443|FQDN-HTTP --> WAF

FQDN-SSH ---> Origin
WAF --> Origin

classDef hidden display: none;
classDef transparent fill-opacity:0,stroke-opacity:0;
%%style HTTPApp fill-opacity:0,stroke-opacity:0;
%%style TCPApp fill-opacity:0,stroke-opacity:0;
```

# Spectrum 設定
アプリケーションタイプで `HTTP / HTTPS` を選択することで、CDN のパイプラインを経由させ、キャッシュや WAF に関するルール適用をおこなうことができます。

https://developers.cloudflare.com/spectrum/reference/configuration-options/

>アプリケーションタイプは、データがエッジからオリジンへ転送されるプロトコルを決定します。オリジンに直接プロキシしたい場合はTCP/UDPを選択してください。CDN、Workers、Bot管理などの製品を設定する場合は、HTTP/HTTPSを選択する必要があります。この場合、トラフィックはオリジンに直接接続するのではなく、Cloudflareのパイプラインを経由します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/f27d487e-e0f7-1627-79f3-76ab871a8105.png)

また、異なるポート定義であれば、以下のように同一 FQDN に対して複数の設定をすることが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/4249cfda-934d-8ec0-2860-f0088ea2c22a.png)

DNS としては、`Type : Spectrum` として 1 つのレコードが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/fc102142-f8ef-75e1-d97c-9af42b3f34be.png)

# 確認

Spectrum レコードで公開されている FQDN 経由で SSH 接続できることを確認しましょう。

```shell:
ssh FQDN.example.com -i ~/.ssh/private_key 
```

Web 通信に関しては、例えば、以下のようなリクエストを送って `403` が返ってくれば、CDN パイプライン経由の WAF でブロックされることが確認できます。

```shell:
% curl https://FQDN.example.com/.env -o /dev/null -w '%{http_code}\n' -s
403
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/9e50d068-0587-8f29-ded1-8354653a1041.png)

# まとめ

Spectrum を使えば、標準ポート以外で  Web 通信を終端し、WAF を適用したり、1つの FQDN に対して Web / Non-Web ポートを両方対応することが可能です。

特殊なポートや標準の CDN だけでは満たせない要件がある場合には、ぜひ検討してみてください。