Virtual private network
===
###### tags: `Note` `vpn`
[toc]
## OpenVPN
#### 發送封包流程
packets 經過 system call 之後傳入 TCP/IP stack,再傳入 TUN/TAP 虛擬網卡中,虛擬網卡用`hard_start_xmit()` 將 packets 加入 skbuffer,並將 packets 從 kernel space 複製到 user space,OpenVPN 再用網卡中的 character device `turn_read()` 讀取 packets,將 packets SSL 加密後透過 socket 送出。
#### 接受封包流程
物理網卡收到 packets,經過 TCP/IP stack,OpenVPN 通過 `link_socket_read()` 接收 packets,SSL 解密,OpenVPN 調用 character device `turn_write()` 寫到虛擬網卡,再將 packets 從 userspace 複製到 kernel space,寫入 skbuffer,再調用 `netif_rx()` 接收,packets 再次進入 TCP/IP stack。
* Layer 3 or Layer 2
* 1194 port (optional)
* 依靠SSL / TLS進行身份驗證和加密
* OpenSSL使用共享密鑰、HMAC身份驗證和256位加密
* OpenVPN支持DHCP和動態IP地址
* 可以將開放源VPN協議配置為使用 TCP或UDP 、並最多支持256位加密

### Advantage
* Open source
* 透過不同的加密和通訊協議組合,能夠適應多種用途
* Bypass firewall
### Disadvantage
* Setting difficult
* Slow
:::spoiler Deployment
### Deployment
```yml=
# docker-compose.yml
version: '2'
services:
ovpn:
image: kylemanna/openvpn
volumes:
- ./data:/etc/openvpn
ports:
- '1194:1194/udp'
cap_add:
- NET_ADMIN
restart: always
```
```bash=
docker-compose run --rm ovpn ovpn_genconfig -u udp://host
docker-compose run --rm ovpn ovpn_initpki
docker-compose up -d
export CLIENTNAME="JyunD"
docker-compose run --rm ovpn easyrsa build-client-full "$CLIENTNAME" nopass
docker-compose run --rm ovpn ovpn_getclient "$CLIENTNAME" > "$CLIENTNAME.ovpn"
```
:::
## WireGuard
* Layer 3 or Layer 2
* UDP 51820 port (optional)
* 併入 Linux 5.6
* iptables 處理流量轉發
* 用加密的 UDP 封裝數據
> 使用 ChaCha20 進行對稱加密,使用 Poly1305 進行數據驗證。
> 利用 Curve25519 進行密鑰交換。
> 使用 BLAKE2 作為哈希函數。
> 使用 HKDF 進行解密
1. 點對點連線
* 在同一區網或都在外網,直接對連
2. 一方為 NAT,一方在外網
* 外網當 server,設定 `persistent-keepalive` 選項維持連結 (client 會送 heartbeat)
3. 雙方為 NAT,用 Bounce Server
* 用 Bounce Server 當中繼,負責轉發
4. 雙方為 NAT,用 UDP NAT 打洞
* STUN 會在中間溝通分配給對方哪些隨機 source port。通信雙方都會和 STUN 進行初始連接,然後它記錄下隨機的 source port,並將其返回給客戶端。
> STUN (Session Traversal Utilities for NAT)是一種網路協定,允許位於 NAT後的 client 找出自己的外網位址,查出自己位於哪種類型的 NAT 之後以及 NAT 為某一個本地 port 所綁定的 Internet 端 port
### Advantage
* 輕量 (kernel module)
* Fast
* Security
* Setting easily
* 可以 host 對接 container
### Disadvantage
:::spoiler Deployment
### Deployment
```bash=
sudo apt install wireguard
wg genkey | tee server_privateKey | wg pubkey > server_publicKey
wg genkey | tee client1_privateKey | wg pubkey > client1_publicKey
```
#### Server
```conf=
# /etc/wireguard/wg-server.conf
[Interface]
Address = 192.168.100.1/24
PrivateKey = ${PrivateKey}
MTU = 1500
ListenPort = 51820
PostUp = iptables -A FORWARD -i ${wg-server} -j ACCEPT && iptables -A FORWARD -o ${wg-server} -j ACCEPT && iptables -t nat -A POSTROUTING -o ${your_nic} -j MASQUERADE
PostDown = iptables -D FORWARD -i ${wg-server} -j ACCEPT && iptables -D FORWARD -o ${wg-server} -j ACCEPT && iptables -t nat -D POSTROUTING -o ${your_nic} -j MASQUERADE
# Client01
[Peer]
AllowedIPs = 192.168.100.2/32
PublicKey = ${PublicKey}
```
#### Client
```conf=
# /etc/wireguard/wg-client.conf
[Interface]
PrivateKey = ${PrivateKey}
ListenPort = 51820
Address = 192.168.100.2/24
DNS = 1.1.1.1
[Peer]
PublicKey = ${PublicKey}
AllowedIPs = 0.0.0.0/0
Endpoint = 140.115.26.31:51820
PersistentKeepalive = 30
```
```bash=
wg-quick up ${config_name}
# wg-quick down ${config_name}
```
:::
## SSTP
客戶端的系統通過TCP(傳輸控制端口)連接到伺服器。 SSL使用443端口連接到伺服器。 要確認連接、它需要用戶身份驗證。 並且、它通常由客戶端進行身份驗證。 該協議使用伺服器證書進行身份驗證。
* Layer 3
* Microsoft 擁有
* TCP 443 port
* 使用SSL / TLS
* 256位AES加密
### Advantage
* bypass firewall
### Disadvantage
* 加密速度較慢
:::spoiler Deployment
### Deployment
:::
## IPSec
IPSec(Internet Protocol Security)是 IETF(Internet Engineering Task Force)制定的一組開放的網絡安全協議。它並不是一個單獨的協議,而是一系列為IP網絡提供安全性的協議和服務的集合。
* 支援 IPv4 和 IPv6 網絡
* IPSec 主要包括安全協議 AH 和ESP,密鑰管理交換協議IKE(Internet Key Exchange)以及用於網絡認證及加密的一些算法等
* AH (Authentication Header)
* 在 IP header 後加上 AH header
* 只認證(包括 IP header),不加密
* 計算 ICV (Integrity Check Value)
* ESP (Encapsulating Security Payload)
* 在 IP header 後加上 ESP header,後面加 ESP Tail
* 認證和加密(不包括 IP header)
* 計算 ICV (Integrity Check Value)
#### 傳輸模式

#### 隧道模式

:::spoiler Deployment
### Deployment
```bash=
wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh
```
:::
## L2TP
L2TP協議包含兩種類型的消息,控制消息和數據消息,消息的傳輸在 LAC 和 LNS 之間進行。L2TP協議通過這兩種消息,擴展了PPP的應用。
* 控制消息
* 用於 L2TP 隧道和會話連接的建立、維護和拆除。在控制消息的傳輸過程中,使用消息丟失重傳和定時檢測隧道連通性等機制來保證控制消息傳輸的可靠性,支持對控制消息的流量控制和擁塞控制。
* 數據消息
* 用於封裝 PPP 數據幀並在隧道上傳輸。數據消息是不可靠的傳輸,不重傳丟失的數據報文,不支持對數據消息的流量控制和擁塞控制。
本身不提供任何加密,通常搭配 IPSec,通過L2TP / IPSec協議傳輸的數據通常會進行兩次身份驗證。 經由隧道傳輸的每個數據包均包含L2TP報頭。 結果、數據被伺服器解復用。 數據的雙重身份驗證會降低性能、但是確實提供了最高的安全性。
* Layer 2
* UDP 1701 port( 僅用在 init)

### Advantage
* 與PPTP不同、它提供了出色的加密和安全性
* 該協議將數據封裝兩次、這意味著需要進行兩次數據驗證
* 該協議不僅適用於台式機、而且適用於移動操作系統
* L2TP在它支持的所有操作系統上都很容易配置
* 多線程支持可提高性能
### Disadvantage
* 由於雙重身份驗證(封裝)、因此性能較慢
* 有一些防火牆可以阻止L2TP協議端口
* 在運行於NAT路由器上的設備上很難配置該協議
## IKEv2/IPSec
* UDP port 500
### Advantage
* 重新連接功能優異
* 穩定性高
* 低延遲
* 速度快
### Disadvantage
* 適用作業平台少
## Comparison
| | OpenVpn TCP | OpenVpn UDP | WireGuard | SSTP | L2TP/IPsec | IKEv2/IPSec |
| -------- | ----------- | ----------- | --------- | ---- | ---------- | ----------- |
| 速度 | 中等 | 快速 | 非常快 | 中等 | 中等 | 快速 |
| 安全性 | 非常好 | 非常好 | 好 | 好 | 普通 | 好 |
| 穩定性 | 非常好 | 好 | 差 | 普通 | 差 | 非常好 |
| 串流媒體 | 普通 | 好 | 普通 | 普通 | 好 | 好 |
| P2P | 好 | 好 | 中 | 好 | 差 | 好 |