OCIでnostrリレーを動かそう (後編)

[前編](https://qiita.com/WhiteCat6142/items/8c4714b66c5c5b95d1d8)まででstrfryのビルドまで行った
strfryの細かい使い方は他のドキュメントに任せるとして後編ではOCIで実際に動かす際に必要なネットワーク周りのセットアップを行っていく

#### OCI側のファイヤーウォールの設定
クラウド上で動くインスタンスはクラウドサービスの提供するファイヤーウォールとインスタンス内部で動くファイヤーウォールの二重になっていることが多い
OCIもそうなのでまずはクラウドサービス側の設定をしていく

まずインスタンスのページを覗くとVirtual cloud networkという項目があるのでそこをクリック
次にその中のsubnet(少なくとも初期状態では1つ)を選択
Security Listsが表示されるのでその中のDefaultを選択
Ingress Rules(外部から内部へのアクセスを管理するルール)という項目が表示されるのでAdd Ingress Rulesを押して
```
Source CIDR: 0.0.0.0/0
Protocol: TCP
Destination Port Range: 80
```
で設定する

ついでにpingが通るように
```
Source CIDR: 0.0.0.0/0
Protocol: ICMP
Type: 8
```
も追加しておく
うまくいっているかpingが通るか確かめる

参考
[Opening up port 80 and 443 for Oracle Cloud servers - DEV Community](https://dev.to/armiedema/opening-up-port-80-and-443-for-oracle-cloud-servers-j35)

:::note info
ICMPの内容はRFCで定義されていてType 8はEcho Requestである
[第12回　TCP/IPプロトコルを支えるICMPメッセージ](https://atmarkit.itmedia.co.jp/ait/articles/0306/13/news002_2.html)
:::

:::note info
Ingressと対になるものはEgressと呼ばれるものでデフォルトで内部から外部へはすべての通信は許可されている
:::

:::note info
statefulとstatelessというのがあるがこれはTCPコネクションが双方向なので本来Ingress, Egress両方を設定しなければならないがstatefulであればコネクションを検知して自動で処理してくれる
[セキュリティ・ルール](https://docs.oracle.com/ja-jp/iaas/Content/Network/Concepts/securityrules.htm#stateful)
:::

#### iptablesの設定

```sh
sudo iptables -I INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo iptables -I INPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT
```

以下で確認
```sh
sudo iptables -L INPUT
```

:::note info
iptables -I INPUTでINPUTというchainの一番最初にルールを挿入する
chainの一番最初から順番に処理されていきACCEPTやREJECTなどでパケットがどのように処理されるか決まる
port forwardingやらネットワークインターフェイスやら意外と奥が深い
:::

:::note info
他のディストリビューションを使っている人はnftablesやfirewalld, ufwを使っているかもしれない
:::

#### nginxの設定
インターネット上の外部のクライアントがいきなりstrfryに接続しても良いがwebsocketの実装は簡易的なものなので余裕があるのならリバースプロキシーを噛ました方が良い
今後wss化したくなったときにも役立つ

```sh
sudo apt install --no-install-suggests nginx
```

念のためのセキュリティー設定
```/etc/nginx/nginx.conf
        server_tokens off;
        ssl_protocols TLSv1.2 TLSv1.3;
```

```/etc/nginx/sites-enabled/websocket.proxy
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
 
server {
    listen 80;
    server_name 127.0.0.1;
    access_log  /var/log/nginx/websocket.access.log;
 
    location / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Host $host;

    proxy_pass http://127.0.0.1:7777;
    }
}
```

邪魔なので消す
```sh
sudo rm /etc/nginx/sites-enabled/default
```

systemdで実行
```sh
sudo systemctl enable --now nginx
```

以下で確認
```sh
sudo systemctl status nginx
```

参考
[NginxでWebsocketリバースプロキシ](https://www.neko6.info/archives/2758)
[Nginxのconf.dとsites-availableとsites-enabledの違い #nginx](https://qiita.com/tomokon/items/e782636c1e5ec6b5dfdc)
[NginxのリバースプロキシでWebソケットを通す際の設定](https://qiita.com/YuukiMiyoshi/items/d56d99be7fb8f69a751b)

:::note info
websocketはhttpからConnection Upgradeして始まる
そのためポートは80である
:::

:::note info
本来はsites-availableに元ファイルを置いてsites-enabledにシンボリックリンクを張る
実際defaultはそうなっていて消していい理由である
:::

#### nmapによる検証 (任意)

ここまでうまく行っているかあなたのPCから通信して確かめる
```sh
sudo apt install nmap
nmap -p T:80 ${your-server-ip}
```
うまくいっていればopenと表示される

参考
[[Linux] ポートスキャンを行う - nmap](https://blog.katsubemakito.net/linux/portscan)

#### strfryの実行

ようやく実行に移る
ちゃんとディレクトリにいるか確認する

以下の設定を変更する
```strfry.conf
    bind = "0.0.0.0"

    port = 7777

    realIpHeader = "x-real-ip"

    enableTcpKeepalive = true
```

以下で起動
```sh
./strfry relay
```

実際にリレーにアクセスしてみて確かめる

ws://${your-server-ip}

[Nostr playground](https://snowcait.github.io/nostr-playground/)
httpsからhttpへのアクセスなのでブラウザーによってはCORSで無効化されているので手動で直さなければならないことに注意
(firefoxの場合:安全でない接続+network.websocket.allowInsecureFromHTTPS)

```sh
cat /var/log/nginx/websocket.access.log
```

#### エンディング
おつかれさまでした
以上でひととおり終わりです
個人向けリレーにする際は攻撃を避けるためにポートを変えるアクセス元を制限する、公開リレーにする際はドメインを買って証明書を発行してwss://xxxx.xxxの形にするなどいろいろな道がありそうです

よきNostrライフを!