インターネット公開サーバのセキュリティ設定、VPSサーバ：firewalld(BLACK-LIST方式)

インターネット公開サーバのセキュリティ設定方針をまとめる。サービス側でlistenするアドレスやアクセス制御する方法もあるが、ここではfiewalldで制限する方法をまとめる。

- publicに許可するサービス(ssh,xrdp)は、定期的にログ監査してIPBLOCKLISTを更新する。
- VPN接続、自宅からは全て許可する。
- 会社からの接続は、NWアドレスで許可する。(グローバルアドレスが固定されないので、NWアドレスで指定する）
- この資料の下部で、各種ログからIPBLOCKLISTを作成する手順を示している。


[サービスで制限](https://qiita.com/harasakih/items/01f4c404236694608a03)

# paln

| ZONE | TARGET | アクセス元と動作 | IPLIST | INTERFACE |
| :--  | :-- | :-- | :-- | :-- |
drop | DROP | アドレス指定で、全拒否 | IPBLOCKLIST | (none) |
trusted | ACCEPT | アドレス指定で、全許可<br>openvpnと自宅をアドレスで指定 | 直接指定 | (none) |
public | default | if & サービスを限定し許可<BR>インターネットからのアクセス | 指定しない | eth0 |
special | default| アドレス＆サービス指定で、許可 | 直接指定 | (none) |

## BLOCK対象のアドレス確認
【2020.08】ログから生成するシェルサンブルを、この資料の下部に追加。

```bash:
### all-access
# grep "connection received from" /var/log/xrdp.log | awk '{print $10;}' | sort | uniq
# grep "Disconnected from" /var/log/secure | awk '{print $8;}' | sort | uniq
# cat /var/named/data/queries.log | awk '{print $7;}'  

### successful
# grep "connection established from" /var/log/xrdp.log | awk '{print $8;}' | sort | uniq
# grep "Accepted publickey" /var/log/secure | awk '{print $11;}' | sort | uniq
```

# zoneごとの設定
## DROP動作：zone=drop

### ipset[ IPBLOCKLIST ]の作成

```bash:
# firewall-cmd --permanent --new-ipset IPBLOCKLIST --type=hash:net
# firewall-cmd --permanent --get-ipsets
# firewall-cmd --reload 
```

### ipset[ IPBLOCKLIST ] をzone[ drop ]に追加

```bash:
# firewall-cmd --permanent --zone=drop --add-source=ipset:IPBLOCKLIST
# firewall-cmd --permanent --info-zone=drop
# firewall-cmd --reload 
アドレス未設定なので空
  
# firewall-cmd --ipset=IPBLOCKLIST --get-entries --permanent
# ipset list 
Name: IPBLOCKLIST
Type: hash:net
Revision: 6
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 376
References: 7
Number of entries: 0
Members:
# firewall-cmd --reload 
```
### ipsetにアドレスを追加

```bash:
# firewall-cmd --permanent --zone=drop --ipset=IPBLOCKLIST --add-entry=www.xxx.yyy.zzz/nn
# firewall-cmd --permanent --zone=drop --ipset=IPBLOCKLIST --add-entries-from-file=IPBLOCKLIST.lst 
```

```conf:IPBLOCKLIST.lst
111.111.111.0/24
222.222.222.0/24
```
### 確認コマンド

```bash:
# ipset list   
# firewall-cmd  --permanent --ipset=IPBLOCKLIST --get-entries
# firewall-cmd  --permanent --info-ipset=IPBLOCKLIST
# firewall-cmd --list-all-zones
drop (active)
  target: DROP
  icmp-block-inversion: no
  interfaces: 
  sources: ipset:IPBLOCKLIST
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

```
## ACCEPT動作：zone=trusted

- VPN接続は、全アクセスを許可する。このため、VPN接続方式はID&PASSではなく証明書認証のみ許可している。
- VPN接続は 10.8.0.0/24 にマスカレードされるのでこのアドレスで指定。openvpn設定と整合性をとる。
- 自宅のグローバルアドレスを指定。

### zone[ trusted ]に、アドレスを追加する

```bash:
# firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
# firewall-cmd --permanent --zone=trusted --add-source=自宅グローバル/32
# firewall-cmd --reload 
# firewall-cmd --list-all-zones
trusted (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: 
  sources: 10.8.0.0/24 自宅グローバル/32
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

# firewall-cmd --get-active-zones 
trusted
  sources: 10.8.0.0/24 自宅グローバル/32
drop
  sources: ipset:IPBLOCKLIST
public
  interfaces: eth0
special
  sources: 会社保有のNWアドレス/16

```



## アドレス＆サービスで動作を設定：zone=special
zone[special]を新規作成し、特定サービスだけ許可する。

### zoneの作成(削除)

```bash:
# firewall-cmd --permanent --new-zone=special
# firewall-cmd --permanent --delete-zone=special
```

### zoneにサービス、ポートを設定

```bash:
# firewall-cmd --permanent --zone=special --set-target=default
# firewall-cmd --permanent --zone=special --add-service=dns
# firewall-cmd --permanent --zone=special --add-source=許可アドレス/24
```

# 参考

## 自分の公開サーバの設定

| ゾーン | TARGET | INTERFACE | SOURCE | SERVICE | PORT |
| :-- | :-- | :-- | :-- | :-- | :-- |
| drop | DROP |  | ipset:IPBLOCKLIST |  |  | 
| public | default | eth0 |  | dhcpv6-client http https ms-wbt ssh OPENVPN | 8080/tcp | 
| special | default |  | 許可アドレス/16 | dns |  | 
| trusted | ACCEPT |  | 10.8.0.0/24 自宅グローバル/32 |  |  | 

# firewalldの出力を見やすく表示するシェル

```bash:/home/admin/rootbin/fwlist.sh 
#!/bin/sh

[ `id -u` != 0 ] && echo "must be root" && exit 1

firewall-cmd --list-all-zones | awk '
BEGIN { 
  flg = 0;
  OFS = " | ";
  print "", "ZONE", "TARGET", "INTERFACES", "SOURCES", "SERVICES", "PORTS", "" ;
}
{
/* 先頭が空白以外で (active) */
  if( /^[^ ].+\(active\)/ ) {
    flg		= 1;
	zone	= $1;
  };
/* 空行 */
  if( flg == 1 && /^[ ]*$/ ) {
    print "", zone, target, interfaces, sources, services, ports, "" ;
    flg		= 0;
  };

/* active zone の詳細を分解、":"で判定 */
  if( flg == 1 && $1 ~ ":") {
    /* TAGを保存し、:でセパレート */
	split($0, a, ": ");
    if($1 == "target:") { target = a[2];}
    if($1 == "interfaces:") { interfaces = a[2];}
    if($1 == "sources:") { sources = a[2];}
    if($1 == "services:") { services = a[2];}
    if($1 == "ports:") { ports = a[2];}
  };
} '
```

# IPBLOCKLISTをログから作成するシェル。
この順
1. mk.ipset1.sh
2. mk.ipset2.sh
3. vi all.success.lst
4. mk.ipset3.sh
5. tmp.IPBLOCK.lst が使うファイル。

## xrdp,sshd,openvpnのログからブロックするリストを作成する

- ``` firewall-cmd --permanent --zone=drop --ipset=IPBLOCKLIST --add-entries-from-file=IPBLOCKLIST.lst ```　で使用するIPBLOCKLIST.lst(tmp.IPBLOCK.lst) を作成する
- 発見した不許可IPは、24bitマスクで拒否する
- 以下シェルソース例の、IP.ADDR.WHITE.A,IP.ADDR.WHITE.B,WHITE.NWADDR は許可されるべき、IPアドレスや、NWアドレス 

### 可否に関わらず、アクセスがあった全てのIPアドレス

```bash:mk.ipset1.sh
#!/bin/sh

XRDP=/var/log/xrdp.log
SSH=/var/log/secure
OVPN=/var/log/openvpn.log

XRDPLST=rdp.all.lst
SSHLST=ssh.all.lst
OVPNLST=ovpn.all.lst

ALLLST=all.all.lst

# all list
echo "processing $XRDP"
grep "connection received from" $XRDP | awk '
{
  if($10 == "IP.ADDR.WHITE.A") next;
  if($10 == "IP.ADDR.WHITE.B") next;
  if($10 ~ /^WHITE.NWADDR/) next;
  print $10;
}' | sort | uniq > $XRDPLST
#
echo "processing $SSH"
grep "Disconnected from" $SSH | awk '
{
  if($8 == "IP.ADDR.WHITE.A") next;
  if($8 == "IP.ADDR.WHITE.B") next;
  if($8 ~ /^WHITE.NWADDR/) next;
  print $8;
}' | sort | uniq > $SSHLST
#
echo "processing $OVPN"
grep "TCP connection established" $OVPN | awk '
{
  if(($7 == "TCP") && ($8 == "connection")) { print $11; }
  if(($6 == "TCP") && ($7 == "connection")) { print $10; }
} ' | awk '
BEGIN{FS = "[\]\:]";}
{
  if($2 == "127.0.0.1") next;
  if($2 == "IP.ADDR.WHITE.A") next;
  if($2 == "IP.ADDR.WHITE.B") next;
  if($2 ~ /^WHITE.NWADDR/) next;
  print $2;
}' | sort | uniq > $OVPNLST

cat $XRDPLST $SSHLST $OVPNLST | sort | uniq > $ALLLST
#
echo "result is $XRDPLST"
echo "result is $SSHLST"
echo "resule is $OVPNLST"
echo "merged to $ALLLST"
```

### アクセスが成功したIPアドレスのリスト。このリストはホワイトリストになっているハズ。

```bash:mk.ipset2.sh
#!/bin/sh

XRDP=/var/log/xrdp.log
SSH=/var/log/secure
OVPN=/var/log/openvpn.log

XRDPLST=rdp.success.lst
SSHLST=ssh.success.lst
OVPNLST=ovpn.success.lst

ALLLST=all.success.lst

# all list
echo "processing $XRDP"
grep "connection established from" $XRDP | awk '{print $8;}' | sort | uniq > $XRDPLST
#
echo "processing $SSH"
grep "Accepted publickey" $SSH | awk '{print $11;}' | sort | uniq > $SSHLST
#
touch $OVPNLST


cat $XRDPLST $SSHLST $OVPNLST | sort | uniq > $ALLLST
#
echo "result is $XRDPLST"
echo "result is $SSHLST"
echo "result is $OVPNLST(null)"
echo "merged to $ALLLST"
```

### 先に作成したホワイトリストの確認と修正。不明なアドレスは削除。

```bash:all.success.lst
vi などで 不明なアドレスを削除
```

### IPBLOCKLISTの作成。
 このシェルでは、tmp.IPBLOCK.lst のファイル名で作成される。

```bash:mk.ipset3.sh 
#!/bin/sh

ALLLST=all.all.lst
SUCCESSLST=all.success.lst
IPBLK=tmp.IPBLOCK.lst

join -v 1 $ALLLST $SUCCESSLST | awk '
BEGIN{ FS=".";OFS=".";}
{ print $1,$2,$3,"0/24";}' | sort | uniq | awk '
{ print;}' > $IPBLK

echo "maked $IPBLK"
```