iptablesが難しいためufwでWEBサーバーのファイアウォール設定

サーバーに簡単にファイアウォールの設定を施してくれるufwの扱い方に関する内容です。

自分でWEBサービスを動かしていますが、インフラに関する知識がまだまだ乏しいため、WEBサービス周りのインフラ環境は貧弱です。しかし、今の時代は小さなサービスでも攻撃を受ける可能性があるため、最低限のセキュリティ対策は必須です。

そこで今回は、最低限のセキュリティ対策としてLinuxサーバーにファイアウォールの設定を施します。この記事では、そのファイアウォールを簡単に設定してくれるufwの使い方をまとめてみました。


# ufwとは
ufw（Uncomplicated FireWall）とは、Linuxの「Netfilter」によるファイアウォールを管理して操作するための**iptablesをラッパー**した機能のことです。

もう少しわかり易く言うなら、Linuxにはパケットフィルタリング(ファイアウォール)やNATを実現するための「Netfilter」という機能を標準で備えています。
これを操作・管理するためのツールとしてiptablesというものがあり、iptablesによって非常に細かい設定が行えます。
## iptablesは設定が困難
iptablesは「何分に数回，sshアクセスを試みてきたIPアドレスからの接続は何秒間かは拒絶する」レベルで、パケットフィルタリングやNATの設定を細かく行えるものの、初心者がいきなりやるのは難しいものです。
当然、ある程度はネットワークの知識が必要であり、インフラエンジニアでない人にとっては少々慣れるのにも時間がかかります。

そこで**iptablesの設定を簡略化してくれるufw**というツールがあり、これを使ってファイウォールの設定を行い、最低限のセキュリティ対策を施します。

当然ですが、ufwでできることはiptablesですべて行えます。しかし、ufwでは基本的な設定は非常に単純なコマンドで同じ機能を実現できます。

# 実際に使ってみる
それでは実際に手を動かしてufwを使っていきましょう。
ufwの操作にはroot権限が必要なため、コマンドの先頭にはsudoをつける必要があります。

まずは以下のコマンドを打ってufwの設定状態を見てみます。

```Terminfo
$ sudo ufw status
Status: inactive
```

inactiveと表示されているように、最初はufwの設定が無効になっているはずです。
そのためufwを一度有効化させるために以下のコマンドを打ちます。

```Terminfo
$ sudo ufw enable
```

上記のコマンドを打つと、人によっては以下のような表示が出る可能性があります。

```Terminfo
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)?
```

「現在のssh接続を中断させる可能性があります。操作を続けますか？」という意味で、ssh接続などでサーバーに繋いでいるユーザーには出るそうです。
自分の環境ではy(yes)を入力してもsshが切断されるなんてことは無かったため、yを入れても問題ないと思います。


```Terminfo
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)?y
Firewall is active and enabled on system startup
```
```Terminfo
$ sudo ufw status
Status: active 

(activeと表示されているため有効)
```
yを入力するとufwが有効化されます。「sudo ufw status」を打てば、ufwが有効か無効かの状態を確認できます。

この状態で以下のコマンドを打つとiptablesにいろんな設定が書き込まれているはずです。

```Terminfo
$ sudo iptables -nL
```


ちなみにufwを無効化したくなった場合は以下のコマンドを打ちます。

```Terminfo 
$ sudo ufw disable
```

## 一度、全ての通信を無効化する

それでは本格的な設定に入っていきます。まずは以下のコマンドを打って、一度全ての通信を無効化します。

```Terminfo
$ sudo ufw default DENY
Default incoming policy changed to 'deny'
(be sure to update your rules accordingly)
```
これにより、外からの通信は全て遮断されます。(現状繋いでいるままのssh接続に関しては途中で切れることはありますが、一度ログアウトすると再度sshから接続するのは不可能になってしまうのでご注意ください)
一度全ての通信を遮断し、ここからそれ以外の**何の通信は許可**するかを決めていきます。

ちなみにこの設定を行っても、無効化した通信はあくまで「外→内」に向かって来る通信であり、「中→外」の外に向かっていく通信は無効化はされていません。

## 実際に設定を行う

ufwの設定で「ポート番号◯◯に来る通信を許可」としたい場合は以下のようにコマンドを打ちます。

```Terminfo
$ sudo ufw allow [ポート番号]
```

逆に「ポート番号◯◯に来る通信を許可しない」としたい場合は以下のようにコマンドを打ちます。

```Terminfo
$ sudo ufw deny [ポート番号]
```
## ssh接続を許可
まずは今後もリモートから接続できるように、ssh接続を許可します。
ssh接続を許可するには、以下のコマンドを打ちます。

```Terminfo
$ sudo ufw allow 22
```
ssh接続は22番ポートなため、22番への通信を許可します。

しかしssh接続のポートである22番の通信を許可して外部(インターネット)に公開すると、必ずと言っていいほど**不特定多数の怪しいホストから22番ポートに接続要求**を受けます。(つまりは不正ログインを試みようとして攻撃を受ける)

22番ポートに対して適当なパスワードを打ち込み、**偶然一致を試みてログイン**出来るように連続でアクセスを試みてきます。これをブルートフォース攻撃とも言います。

これの対策として、「連続してアクセスしてくるIPアドレスの接続を許可しない」設定を施しましょう。以下のコマンドを打ちます。

```Terminfo
$ sudo ufw limit 22
```
これにより**「30秒間の間に6回以上接続を試みた IP アドレスを許可しない」**ルールが設定されます。

一度これで設定を確認します。以下のように表示されるはずです。

```Terminfo
$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22                         LIMIT       Anywhere                  
22 (v6)                    LIMIT       Anywhere (v6)    
```

IPv4とIPv6の22番ポートに対してLIMIT(接続制限)が設定されています。

### 特定のネットワークからのssh接続のみ許可

上記の設定を施したとしても外部のインターネットにsshのポートを晒していることに変わりはありません。接続の回数に制限を設けたとしても、**何らかの方法でパスワードを推測されて接続**をされてしまったり、脆弱性を付いた攻撃などから接続をされてしまうことも考えられます。

そのため、sshの接続を許可するのは**内部からのネットワークのみ**にして、**外部からのssh接続は全て許可しない**設定にしてしまいましょう。

以下の画像のようなネットワークの構成でサーバーを建てていたと仮定します。

![192.168.1.0.png](https://qiita-image-store.s3.amazonaws.com/0/171824/2f546870-dfe9-60ea-94bd-a3fa54268161.png)

ローカルエリアネットワーク内には「192.168.1.10」のIPアドレスが振られたホストがあります。**このホストからのみssh接続を許可**する。又は**このネットワーク(192.168.1.0/24)からのみssh接続を許可する**ように設定するには以下のようなコマンドを打ちます。

```Terminfo
(192.168.1.0/24からのssh接続を許可)
$ sudo ufw allow from 192.168.1.0/24 to any port ssh
Rule added
```

```Terminfo
(192.168.1.10からのssh接続を許可)
$ sudo ufw allow from 192.168.1.10 to any port ssh
Rule added
```
設定を確認してみると、以下のようになっているはずです。

```Terminfo
(192.168.1.0/24からのssh接続を許可した場合の結果)
$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22                         LIMIT       Anywhere                  
22                         ALLOW       192.168.1.0/24            
22 (v6)                    LIMIT       Anywhere (v6)   
```

ただし、この状態でも外部からの接続回数制限付きのssh接続を許可してしまいます。
そのため、LIMITをつけているルールを削除します。

以下のコマンドでルール番号を表示して設定を確認します。

```Terminfo
$ sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22                         LIMIT IN    Anywhere                  
[ 2] 22                         ALLOW IN    192.168.1.0/24            
[ 3] 22 (v6)                    LIMIT IN    Anywhere (v6)      
```

上記の用に表示された場合、1と3のルールが不要なため、番号を指定してルールを削除してしまいましょう。

```Terminfo
$ sudo ufw delete 1
Deleting:
 limit 22
Proceed with operation (y|n)? y
Rule deleted
```

これで1番のルールが削除されました。3番も上記同様にルールを削除します。

### WEBへのアクセスを許可する

WEBサーバーのファイアウォールを設定するのが今回の目的なので、80(HTTP)と443(HTTPS)への接続を許可しなければいかません。

ポート番号を指定して接続を許可するのもいいですが、**アプリケーションを指定しての設定**も行えます。
以下のコマンドでアプリケーションの一覧が見れます。

```Terminfo
$ sudo ufw app list
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH
```
自分の場合はWEBサーバーにNginxを使っているため、Nginxがアプリケーションの一覧として表示されます。(Apacheをインストールして起動している場合はApacheが表示されます)

以下のコマンドでNginxを指定して、NginxへのHTTP(80),HTTPS(443)の接続を許可します。

```Terminfo
$ sudo ufw allow 'Nginx Full'
Rule added
Rule added (v6)
```

設定を確認すると以下のようになっているはずです。

```Terminfo
$ sudo ufw status
sudo: unable to resolve host 133-130-116-227
Status: active

To                         Action      From
--                         ------      ----
22                         ALLOW       192.168.1.0/24            
Nginx Full                 ALLOW       Anywhere                  
Nginx Full (v6)            ALLOW       Anywhere (v6)  
```

これで外部から80,443(WEB)へのアクセスが行えるようになりました。
# まとめ
現状ufwで行ったファイアウォール設定は以下です。

- 一旦、外部からの接続は全て遮断
- 192.168.1.0/24のネットワークからのみssh接続を許可
- 外部からの80,443ポートのWEBサーバーへの接続を許可

iptablesは細かい設定を行えるものの、設定が非常に複雑です。
ufwではコマンド一つでファイアウォールの設定が簡単に行えます。

ただし、**本格的なファイアウォールを構築しようと思った場合は、iptablesをある程度使いこなせる**ようにする必要があります。

自分も正直まだまだ勉強中です。
※一部ご指摘などがあれば教えていただけると幸いです。

## 参考資料
ufw

- http://himachannel.com/information-technology/linux/post-118
- http://gihyo.jp/admin/serial/01/ubuntu-recipe/0353
- http://gihyo.jp/admin/serial/01/ubuntu-recipe/0076?page=1
- http://gihyo.jp/admin/serial/01/ubuntu-recipe/0077?page=1
- https://gtrt7.com/blog/linux/ufw-setting#2


iptables

- https://knowledge.sakura.ad.jp/4048/