Flaskで立てたサーバーが外部からアクセスできない場合に確認すべきこと


# 外部からアクセスできない場合に確認すべきこと

flaskでサーバーを立ち上げたときにlocalhostからは通信が可能だが、外部から通信ができない場合に確認すべきことについてまとめました。先日ひどいめにあったので。
flask関係なく通信エラー時に確認すべきことも含みます。


## サンプル

一番シンプルなサンプルコードを載せます。
flaskコマンドではなくpython側で実行してるので、flaskコマンド使用者はうまく読み替えてください。
問題ない方はここは読み飛ばしても構いません。

```python
from flask import Flask

app = Flask(__name__)


@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"


def main():
    app.run()


if __name__ == '__main__':
    main()
```

こちら実行すると、以下のような出力になります。アクセス時の出力も出てます。

```shell
 * Serving Flask app 'flask_test'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [01/Oct/2022 11:32:10] "GET / HTTP/1.1" 200 -
```

別のターミナルからcurlを投げるとこのように返ってきます。
```shell
$ curl -i localhost:5000/
HTTP/1.1 200 OK
<省略>
<p>Hello, World!</p>
```


ここまでで、以下のことがわかりますので参考程度に。
* app.runはデフォルトでport:5000で起動する
* app.runはデフォルトでdebug mode: off
* app.routeはデフォルトでGET

## コードレベル

ここから実際に外部からアクセスできない場合の対処法です。

#### hostの設定

以下の記事が参考になりました。公式Documentに、hostを指定しないとlocalhostからしかアクセスできないようになってますと書いてあります。

https://qiita.com/tmokmss/items/122dfdb41188176e45b5

https://flask.palletsprojects.com/en/0.12.x/quickstart/

> Externally Visible Server
If you run the server you will notice that the server is only accessible from your own computer, not from any other in the network. This is the default because in debugging mode a user of the application can execute arbitrary Python code on your computer.
If you have the debugger disabled or trust the users on your network, you can make the server publicly available simply by adding --host=0.0.0.0 to the command line:
`flask run --host=0.0.0.0`
This tells your operating system to listen on all public IPs.

なので、以下のようにhostを指定して実行する。
```python
 app.run(host="0.0.0.0")
```

また、Laravel artisanコマンドとかでも同様にhostの指定が必要。


#### debug=Falseとなっているか 

上の公式の文章から、debuggerが有効な場合にも外部公開されないと書いてあります。
デフォルトでは無効ですが、設定ミスや開発時のコードが残ってたりなど確認すべきです。

>  This is the default because in debugging mode a user of the application can execute arbitrary Python code on your computer.

```python
 app.run(host="0.0.0.0", debug=False)
```

## 通信設定

主にAWSのEC2を前提として進めます。

### ポートが開放されているか

指定してるportもしくはデフォルトの5000ポートが開いてるかの確認。
AWSの　EC2 > 対象のインスタンス > セキュリティ > インバウンドルール　を確認する。
該当のport範囲が開いていない場合、セキュリティグループ  > インバウンドルールの編集 > ルールを追加 でルールを追加する。
カスタムTCP, 該当port, カスタム, 0.0.0.0 で可能だと思いますが詳しくないので詳細は割愛。

### ファイアウォールの設定

#### 注意：下手するとSSH接続できなくなったり余計にややこしいことになるので一番最後に確認してください。AWS利用中の方は上記内容だけで十分なので、絶対にやらなくていいと思います。


前述とほぼ同じ内容ではあるが、ubuntu側でファイアウォールを設定する方法になります。
試したのですが、どうやらUbuntuのEC2を使用中の場合セキュリティグループよりもこちらのufwのルールの方が優先される気がします。***ファイアウォールを有効にした際には、SSH接続を許可しないと接続できなくなります。***

https://hana-shin.hatenablog.com/entry/2022/01/31/233228


### URLは間違っていないか？

pathの確認です。すべてのプログラムのエラーの原因の要素です。
誤字がないか、行末の ”/” の有無など確認します。


## 通信状況

外部からの操作で確認。

### StatusCodeの確認

curlで投げてみます。
```shell
$ curl -i localhost:5000/
HTTP/1.1 200 OK
```
このとき、うまくいってない場合はStatusCode が40X か 50X だと思います。
時間がかかった後にConnection Refusedとなる場合は、そもそも通信ができてないので上述のportが開いてるか、サーバー側でプロセスが立ち上がっているかを確認してください。
```shell
 (7) Failed to connect to localhost port 80 after 2254 ms: Connection refused
```

StatusCodeが返ってきた場合は、こんなイメージで考えます。
40X : Client側に原因あり
50X : Server側に原因あり

40X系であれば、ステータスコードから原因を調べてもらえれば。


50X系であれば、flaskの出力側でエラーが出てないか確認してください。
また、proxyやgatewayを使用してる場合にそこでエラーが生じると500系のエラーになるのでそちらのログも要確認です。


### telnetでの確認

上述の通信設定の確認になります。
以下の記事が参考になりました。

http://teqspaces.com/Linux/9


```shell
curl -v telnet://{ホスト名もしくはIPアドレス}:{ポート番号}
```


## その他

### ログや出力の確認

タイトル通りです。。



他にもここを確認すべきとかあれば指摘お願いします。

## 参考記事

https://qiita.com/tmokmss/items/122dfdb41188176e45b5

https://hana-shin.hatenablog.com/entry/2022/01/31/233228

http://teqspaces.com/Linux/9