FileMakerのWebDirect公開をnginxでリバースプロキシ

# はじめに
## 対象読者
* Claris FileMaker Server ( 以下 FMS ) で WebDirect を使っている／使おうとしている
* WebDirect の公開 URL を、 FMS に設定されているサブドメインとは別のものを指定したい
    * たとえば……
        * 公開 URL https://xxxxxx.xxx/fmi/webd/
        * FMS に指定されているサブドメイン https://yyyyyy.yyy/fmi/webd/
* FMS 稼働サーバの IP アドレスを知られるのは嫌
* FMS 稼働サーバに直接アクセスされたくない

## やること
* リバースプロキシサーバの用意

## 前提
* 既に FMS に指定されているサブドメイン https://yyyyyy.yyy/fmi/webd/ へアクセスできること
* FMS 側のファイアウォールで接続元 IP を制限している
* FMS 側でクライアント接続元 IP が取得できなくてもかまわない

## 環境
### リバースプロキシサーバ
* OS は Ubuntu 20.04 を想定
    * 他の Linux ディストリビューションをお使いの場合、必要に応じて apt コマンドを読み替えてください

### FMS サーバ
* OS は Windows Server 2016 以上を想定
    * 試行した環境は 2016 ですが 2019 でも問題ないと思われる
* FMS の ver. は 17 以上を想定
    * 試行した環境は 17 と 19


# 本題
## リバースプロキシサーバの用意
### 証明書の準備
* 手元にある証明書
* もしくは Let's Encrypt
    * いくつか、私の他記事で導入に関して書いているのでそちらご参照ください
        * [JitsiMeetをUbuntu20.04にインストール～動作検証までしてみる](https://qiita.com/Hi_Noguchi/items/4f29c68cf2d446489dc6)
        * [Ubuntu20.04でPrometheusを用いてリソースモニタリング（環境構築編）](https://qiita.com/Hi_Noguchi/items/95e7d2b9a3f2857e9ff9)

### nginx のインストール
* コマンド

```sh
apt install nginx
```

### nginx の設定
* `/etc/nginx/sites-available/default` に記述
    * FileMaker Server を `xxxxxx.xxx` で、リバースプロキシサーバを `yyyyyy.yyy` とする
    * upstream の名前を `filemakerserver-webdirect-upstream` とする
        * upstream ディレクティブの server はサブドメインより IP address を直接指定してあげた方が nginx のパフォーマンスは高くなるけれど、ここではひとまず分かりやすくサブドメインを指定しておく
    * 80 port でアクセスされたら強制的に 443 port へリダイレクトする
    * 証明書は任意に指定

```nginx:/etc/nginx/sites-available/default
upstream filemakerserver-webdirect-upstream {
  server xxxxxx.xxx:443;
}

server {
  listen 80;
  server_name yyyyyy.yyy;

  if ($host = yyyyyy.yyy) {
    return 301 https://$host$request_uri;
  }

  return 404;
}

server {
  listen 443 http2 ssl;
  server_name yyyyyy.yyy;

  location / {
    try_files $uri @filemakerserver-webdirect-upstream;
  }

  location @filemakerserver-webdirect-upstream {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_cache_bypass $http_upgrade;
    proxy_pass https://filemakerserver-webdirect-upstream;
  }

  ssl_certificate /etc/letsencrypt/live/yyyyyy.yyy/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/yyyyyy.yyy/privkey.pem;
}
```

### nginx リロード
* コマンド

```sh
nginx -s reload
```

### ufw で nginx へのアクセスを通す設定
* ufw はファイアウォールです
    * いくつか、私の他記事で導入に関して書いているのでそちらご参照ください
        * [JitsiMeetをUbuntu20.04にインストール～動作検証までしてみる](https://qiita.com/Hi_Noguchi/items/4f29c68cf2d446489dc6)
        * [Ubuntu20.04でPrometheusを用いてリソースモニタリング（環境構築編）](https://qiita.com/Hi_Noguchi/items/95e7d2b9a3f2857e9ff9)
* コマンド

```sh
ufw allow 'Nginx Full'
```

## アクセス確認
* https://xxxxxx.xxx/fmi/webd/ へアクセスしたときに正しく表示されればよしです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/2a8aa595-8059-974e-e253-851b25a6cb11.png)


# おわりに
## 感想
* proxy_set_header X-Forwarded-Host を設定するとうまくいかなくなるというのが、ポイントでした。おそらく一度 IIS 側で受け取ったものをさらに FMS 側へ渡すという多段のかたちをとっているからなのではないか……？　と推察されます。

## 2020/10/08 追記
* FileMaker Server 19 でも動作確認しました。FMS 17 では出なかった `failed: Error during WebSocket handshake: Unexpected response code: 501` エラーが出るようになりました。
* これへの対応として nginx の以下 location 内に `proxy_http_version 1.1;` `proxy_set_header Upgrade $http_upgrade;` `proxy_set_header Connection "upgrade";` `proxy_cache_bypass $http_upgrade;` を追記しています。最終的には以下のように（本文記事内でも修正済）
    * 参考記事 : [Docker & Node.js & Socket.io & NGINXでよくあるエラー](https://qiita.com/risto24/items/d8c2fcbade582a15ca29)

```nginx
  location @filemakerserver-webdirect-upstream {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_cache_bypass $http_upgrade;
    proxy_pass https://filemakerserver-webdirect-upstream;
  }
```