VPS(centos7)にopenvpnを立てる(tun版)

# VPS(ntt-pc,webarena)にVPNサーバを立てた。

[Raspi0WのOSMCにVPNを立てた](https://qiita.com/harasakih/items/4c0e4fe24b144e178b46)
[先達のサイト](https://qiita.com/horus19761108/items/9c7879149218d9325c5e)

# 【サーバ】openvpn-serverのinstall
前述の先達のサイトを参考、省略。```cd /etc/openvpn/easy-rsa```、以降このディレクトリで作業

## ディレクトリ初期化
```bash:
./easyrsa init-pki
```
ディレクトリ /etc/openvpn/easy-rsa/pki が作成される

## 認証局
```bash:
./easyrsa build-ca
```
/etc/openvpn/easy-rsa/pki/private/ca.key
/etc/openvpn/easy-rsa/pki/ca.crt
が作成される


## DHパラメータの作成
```bash:
./easyrsa gen-dh
```
/etc/openvpn/easy-rsa/pki/dh.pem
が作成される

## サーバ証明書、秘密鍵
```bash:
./easyrsa build-server-full server nopass
```
/etc/openvpn/easy-rsa/pki/private/server.key
/etc/openvpn/easy-rsa/pki/reqs/server.req
/etc/openvpn/easy-rsa/pki/issued/server.crt
が作成される

## クライアント用の証明書と秘密鍵の作成
```bash:
./easyrsa build-client-full client1 nopass
```
/etc/openvpn/easy-rsa/pki/private/client1.key
/etc/openvpn/easy-rsa/pki/reqs/client1.req
/etc/openvpn/easy-rsa/pki/issued/client1.crt
が作成される。client1は、接続ユーザ毎に指定・作成する。

## TLS認証キーの作成
```bash:
openvpn --genkey --secret /etc/openvpn/ta.key
```
/etc/openvpn/ta.key が作成される


# pkiに作成されたファイルの配置
### サーバ
 openvpnのサーバ設定(/etc/openvpn/server.conf)を整合していること

```bash
cp -i /etc/openvpn/easy-rsa/pki/ca.crt /etc/openvpn  ;
cp -i /etc/openvpn/easy-rsa/pki/dh.pem  /etc/openvpn  ;
cp -i /etc/openvpn/easy-rsa/pki/private/server.key /etc/openvpn ;
cp -i /etc/openvpn/easy-rsa/pki/issued/server.crt /etc/openvpn ;
```

### クライアント
 openvpnのクライアントファイル(*.ovpn)に取り込まれるファイルを、/etc/openvpn/clientに配置する。後述する、make_ovpn.shと整合していること。
※ client1.crt, client1.key は、openvpnサーバに配置されていなくてもよい。

```bash
CLIENT=client1 ;
cp -i /etc/openvpn/easy-rsa/pki/ca.crt   /etc/openvpn/client ;
cp -i /etc/openvpn/easy-rsa/pki/issued/$CLIENT.crt  /etc/openvpn/client ;
cp -i /etc/openvpn/easy-rsa/pki/private/$CLIENT.key  /etc/openvpn/client ;
cp -i /etc/openvpn/ta.key  /etc/openvpn/client ;
```

# 【サーバ】openvpn-server設定ファイル
デフォルトはudp1194ですが、Firewallを通りやすいtcp443で設定します。
```cat /etc/openvpn/server.conf  | grep -v '^[#;]' | grep -v '^\s*$'```

```conf:server.conf
port 443
proto tcp
dev tun
ca   /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key  /etc/openvpn/server.key  # This file should be kept secret
dh /etc/openvpn/dh.pem
server 10.8.0.0 255.255.255.0 # VPNクライアントに付与されるアドレス
ifconfig-pool-persist ipp.txt
push "route www.xxx.yyy.zzz 255.255.255.0"  # これは不要かも
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS WWW.XXX.YYY.ZZZ"
keepalive 10 120
tls-auth /etc/openvpn/ta.key 0
cipher AES-256-CBC
persist-key
persist-tun
status openvpn-status.log
log-append  /var/log/openvpn.log
verb 3
explicit-exit-notify 0
```
www.xxx.yyy.zzz : VPSのアドレス
WWW.XXX.YYY.ZZZ : VPSのDNSアドレス
push "route www.xxx.yyy.zzz 255.255.255.0" : VPNサーバ経由でアクセス許可する、プライベートアドレス「www.xxx.yyy.zzz / 255.255.255.0]
push "redirect-gateway def1 bypass-dhcp" : VPNクライアントの通信はVPNサーバ経由

# 【クライアント】VPNクライアント設定ファイル
iPhone用接続アプリ[OpenVPN Connect](https://itunes.apple.com/jp/app/openvpn-connect/id590379981?mt=8)は、以下の設定ファイル ```webarena.ovpn```を、iPhoneにメール送付すると、アプリに取り込んでくれる。
このクライアント設定ファイルを作成するシェル。

```bash:make_opvn.sh 
#!/bin/sh

usage() {
  echo "usage : `basename $0` client-name"
  ls /etc/openvpn/easy-rsa/pki/issued
  ls /etc/openvpn/easy-rsa/pki/private
  exit 1
}

[ $# -eq 0 ] && usage

OVPN="$1.ovpn"              # クライアント設定ファイル

CA=/etc/openvpn/ca.crt
CLIENTCERT=/etc/openvpn/easy-rsa/pki/issued/$1.crt
CLIENTKEY=/etc/openvpn/easy-rsa/pki/private/$1.key
TLSKEY=/etc/openvpn/ta.key

[ ! -e $CA ] && echo "$CA : CA not found"
[ ! -e $CLIENTCERT ] && echo "$CLIENTCERT : CLIENTCERT not found"
[ ! -e $CLIENTKEY  ] && echo "$CLIENTKEY : CLIENTKEY not found"
[ ! -e $TLSKEY     ] && echo "$TLSKEY : TLSKEY not found"

cat << __EOT__ > $OVPN
tls-client
key-direction 1
dev tun
proto tcp-client    # tcp-client or udp
port  443
remote wwww.xxxx.yyy.zzzz
cipher AES-256-CBC
__EOT__

echo "<ca>"     >> $OVPN
cat $CA         >> $OVPN
echo "</ca>"    >> $OVPN

echo "<cert>"   >> $OVPN
cat $CLIENTCERT >> $OVPN
echo "</cert>"  >> $OVPN

echo "<key>"    >> $OVPN
cat $CLIENTKEY  >> $OVPN
echo "</key>"   >> $OVPN

echo "<tls-auth>"    >> $OVPN
cat $TLSKEY          >> $OVPN
echo "</tls-auth>"   >> $OVPN
```
/etc/openvpn/client/$1.ovpn が作成される。
www.xxx.yyy.zzz VPNサーバのIPアドレス

# クライアントの追加
```bash:
# cd /etc/openvpn/easy-rsa
# CLIENT=hoge
# ./easyrsa build-client-full $CLIENT nopass
# cp -i /etc/openvpn/easy-rsa/pki/issued/$CLIENT.crt  /etc/openvpn/client 
# cp -i /etc/openvpn/easy-rsa/pki/private/$CLIENT.key  /etc/openvpn/client 

# make_opvn.sh $CLIENT

# cat ./$CLIENT.ovpn
```

# 【サーバ】OSのforward設定
 sysctlで、フォワード設定をします。

```bash:
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/ipv4.forward.conf
```


# 【サーバ：NAT】iptables(firewall-cmd)の設定
> [centosでopenvpn用の iptables を firewall-cmd で設定する](https://gtrt7.com/blog/linux/install-openvpn#1)

- インターネットからVPNサーバへの通信を許可
- VPNクライアントからの接続をmasqueradeして、上位IFへ流す
- firewall-cmdのpublicゾーン：上位IF、trustedゾーン：VPNクライアントからの接続、に設定します

## ゾーンの確認
``` 
# firewall-cmd --list-all-zones
```

## インターネットからVPNサーバへの通信を許可
```
# firewall-cmd --permanent --add-service=openvpn   ## デフォルト(1194/udp)の時
# firewall-cmd --permanent --add-service=https     ## 443/tcpの時

```


## IPマスカレード設定を追加する
### 設定
10.8.0.0/24をインタフェース eth0 にマスカレードする

```
# firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE  
```

### 確認
```
# firewall-cmd --permanent --direct --get-all-passthrough 
----
ipv4 -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

# firewall-cmd --permanent --direct --query-passthrough ipv4 -t nat  -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE  
----
yes
```

### 削除（おまけ）
```
# firewall-cmd --permanent --direct --remove-passthrough ipv4 -t nat  -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE  
# firewall-cmd --permanent --direct --get-all-passthrough 
----
(null)
````

## trustedゾーンにインタフェース、アドレスを紐付け
### 設定
```
# firewall-cmd --permanent --zone=trusted --add-interface=tun+
# firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
# firewall-cmd --permanent --zone=trusted --add-service=https  # tcp443を使う時
# firewall-cmd --permanent --zone=trusted --add-service=openvpn # defaultの時
```

### 確認
```
# firewall-cmd --reload 
# firewall-cmd --list-all-zones

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: https openvpn
  ports: 
----
trusted (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: ## なぜか表示されません
  sources: 10.8.0.0/24 ## これは表示される
  services: https openvpn  ## server.confの設定によりどちらか
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

# firewall-cmd --get-active-zones 
---
public
  interfaces: eth0
trusted
  interfaces: tun+
  sources: 10.8.0.0/24
```

# openvpn-serverの起動
## systemctl
```bash:
systemctl enable openvpn@server 
systemctl start  openvpn@server
```

## selinux
ausearch,audit2allowでコツコツと対処

```bash:
ausearch --message AVC | grep openvpn
ausearch --message AVC | grep openvpn | audit2allow --module-package=openvpn 
cat openvpn.te
semodule -i openvpn.pp
```

## NW関連
- home-gwのポートフォワード設定

# ユーザID＆パスワード認証に変更する
 IP内線電話(asterisk)を個人利用ではなく、グループで使おうとしている。IP内線電話が

- 自宅WIFI(under homegateway)は利用可
- ４G回線から不可能
- 4G回線経由のVPNは可能

なので、**IP内線電話はVPN接続で利用する**。
このため、VPN接続をグループ内不特定多数の開放したい。不特定多数での利用では、クライアント毎にクライアント証明書作成と設定ファイルの配布が必要で煩雑。
だから、ユーザIDを使い回すことにする。



## サーバ設定
 参考サイト１では、自前の認証プログラムが紹介されているが、参考サイト２を参考にlinux-osのユーザ＆パスワード認証を使う。

[参考1-1](https://www.openvpn.jp/document/authentication-methods/)
[参考1-2](https://www.openvpn.jp/document/openvpn-sqlite-auth/)
[参考2](https://vogel.at.webry.info/201504/article_2.html)

### サーバ設定ファイル

```conf:/etc/openvpn/server.conf
# grep -vE "^#|^;|^\s*$" /etc/openvpn/server.conf

port 443
proto tcp
dev tun
ca   /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key  /etc/openvpn/server.key  # This file should be kept secret
dh /etc/openvpn/dh.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route VPNサーバのグローバルアドレス 255.255.255.0"
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS クライアントに通知するDNSアドレス"
keepalive 10 120
tls-auth /etc/openvpn/ta.key 0
cipher AES-256-CBC
max-clients 20
persist-key
persist-tun
status openvpn-status.log
log-append  /var/log/openvpn.log
verb 3
explicit-exit-notify 0
script-security 1
plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so login
client-cert-not-required
username-as-common-name
```
### VPN認証用ユーザの作成
グループは(-g 99: nobody)、ユーザID(-u nnnn)は重複せず任意で。

```bash:
mkdir /home/ovpn000 
useradd -M -N -d /home/ovpn000 -g 99 -s /sbin/nologin -p パスワード -u 2000 ovpn000 
useradd -M -N -d /home/ovpn000 -g 99 -s /sbin/nologin -p パスワード -u 2001 ovpn001
```

理由は不明ですが、上記でVPNアクセスしたら認証エラーになってしまう。
別のコマンドでパスワードを設定したら認証された。

```bash:
echo "ovpn000:パスワード" | chpasswd
```


### VPN接続時は外部アクセス（インターネット）禁止にする。
 VPNクライアントは、IP内線電話のみ許可し、他を拒否したいので。VPNセグメントから他IFへのフォワードを拒否する。上記で許可した、**【サーバ】OSのforward設定**を無効にする（コメントで潰す）。

```conf:/etc/sysctl.d/ipv4.forward.conf
#net.ipv4.ip_forward=1
```


## クライアント設定
 次のファイルを、openvpnクライアントをインストールしたスマホにメールして取り込む。
```<ca>...</ca>``` と ```<tls-auth>...</tls-auth>``` は上記の証明書認証で作成したファイルの内容です。

### クライアント設定ファイル
```conf:
tls-client
key-direction 1
dev tun
proto tcp
port  443
remote VPNサーバのアドレス(FQDNも可)
cipher AES-256-CBC
auth-user-pass
<ca>
....
</ca>
<tls-auth>
....
</tls-auth>
```