使用WireGuard搭建VPN服务

18.08.23更新

关于apt-get update无法解析源域名的问题,原因是预制的服务商镜像源并不对外开放(阿里、京东、腾讯均无法解析),不是DNS服务无法解析。更换为清华大学源(等开放镜像源)即可解决问题:

结果并不完美,不建议用VPN来科学上网。

实验的VPS配置:

  • 两台国内VPS,一台京东VPS(作为服务端),一台腾讯VPS(作为客户端)
  • 操作系统均为Ubuntu16.04

安装WireGuard

使用指令安装:

add-apt-repository ppa:wireguard/wireguard
apt-get update
apt-get install wireguard

生成密钥

  1. 使用umask获取权限
    • umask 077
  2. 生成密钥文件
    • wg genkey | tee server_privatekey | wg pubkey > server_publickey //生成服务端密钥
      wg genkey | tee client_privatekey | wg pubkey > client_publickey //生成客户端密钥

配置服务端

  1. 编辑配置文件

    • 在/etc/wireguard/目录下创建文件wg0.conf
    • 在wg0.conf中添加
      [Interface]
      Address = 10.200.200.1/24 # 此项为VPN内网地址
      SaveConfig = true
      PrivateKey = [服务端私钥]
      ListenPort = 51820 # 可自定udp监听端口
      
      [Peer]
      PublicKey = [客户端公钥]
      AllowedIPs = 10.200.200.2/32 # 此项为客户端连接内网地址
    • wg0.conf 文件会生成名称为wg0的网络接口,变更名称可以变更接口名
  2. 开启WireGuard网络接口

    • 如果没有以root用户创建配置文件,需要更改文件所属用户:
      • chown -v root:root /etc/wireguard/wg0.conf
    • 给配置文件以权限:
      • chmod -v 600 /etc/wireguard/wg0.conf
    • 开启网络接口:
    • 使用ifconfig可以查看网络接口,开启后可以看到名为wg0的接口
  3. 开启IP转发

    • 编辑 /etc/sysctl.conf,添加行:
      • net.ipv4.ip_forward=1
    • 接着输入以下指令即时开启转发:
      • sysctl -p
        echo 1 > /proc/sys/net/ipv4/ip_forward
  4. 配置防火墙

    • 跟踪VPN链接:
      • iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
        iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    • 允许监听端口的VPN链接:
      • iptables -A INPUT -p udp -m udp --dport 51820 -m conntrack --ctstate NEW -j ACCEPT
    • 允许DNS解析的tcp和udp链接:
      • iptables -A INPUT -s 10.200.200.0/24 -p tcp -m tcp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
        iptables -A INPUT -s 10.200.200.0/24 -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
    • 允许转发在VPN通道内的数据包:
      • iptables -A FORWARD -i wg0 -o wg0 -m conntrack --ctstate NEW -j ACCEPT
    • 设置NAT:
      • iptables -t nat -A POSTROUTING -s 10.200.200.0/24 -o eth0 -j MASQUERADE
    • 安装iptables-persistent使设置在重启后保持有效:
      • apt-get install iptables-persistent
        systemctl enable netfilter-persistent
        netfilter-persistent save
  5. 配置DNS服务

    • DNS解析服务选择了unbound,效果不是很好,有些链接无法解析,可更换其他DNS方案
    • 安装unbound:
      • apt-get install unbound unbound-host
    • 下载根域名服务器表:
      • curl -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache
    • 编辑 /etc/unbound/unbound.conf 配置文件
      • 注释掉include行
      • 添加以下内容:
        server:
        
          num-threads: 4
        
          #开启日志
          verbosity: 1
        
          #根DNS服务器表
          root-hints: "/var/lib/unbound/root.hints"
        
          #为DNSSEC使用根服务器密钥
          auto-trust-anchor-file: "/var/lib/unbound/root.key"
        
          #回应所有接口的DNS请求
          interface: 0.0.0.0
          max-udp-size: 3072
        
          #允许访问DNS服务器的IP
          access-control: 0.0.0.0/0                 refuse
          access-control: 127.0.0.1                 allow
          access-control: 10.200.200.0/24         allow
        
          #不允许返回公共互联网名称
          private-address: 10.200.200.0/24
        
          #隐藏DNS服务器信息
          hide-identity: yes
          hide-version: yes
        
          #防止域名欺骗并使用DNSSEC
          harden-glue: yes
          harden-dnssec-stripped: yes
          harden-referral-path: yes
        
          #添加一个多余回复阈值来清理缓存,并尽可能避免DNS投毒
        Add an unwanted reply threshold to clean the cache and avoid when possible a DNS Poisoning
          unwanted-reply-threshold: 10000000
        
          #将验证失败写入日志
          val-log-level: 1
        
          #缓存条目的最短生存期(s)
          cache-min-ttl: 1800 
        
          #缓存条目的最长生存期
          cache-max-ttl: 14400
          prefetch: yes
          prefetch-key: yes
    • 添加权限并开启unbound:
      • chown -R unbound:unbound /var/lib/unbound
        systemctl enable unbound
  6. 配置好的服务端

    • 使用wg指令可以查看当前开启的WireGuard网络接口:

配置客户端

  1. 编辑配置文件

    • 在/etc/wireguard/目录下创建文件wg0_client.conf
    • 在文件中添加:
      [Interface]
      Address = 10.200.200.2/32 # 服务端配置的客户端内网地址
      PrivateKey = [客户端私钥]
      DNS = 10.200.200.1 # DNS服务,服务端内网地址
      
      [Peer]
      PublicKey = [服务端公钥]
      Endpoint = [服务端的公网IP]:51820
      AllowedIPs = 0.0.0.0/0 
      PersistentKeepalive = 21
      
  2. 开启WireGuard

    • wg-quick up wg0-client

一些问题

  1. 连接到服务端后ssh链接会即刻断开,如果需要连接客户端,需要登录服务端,再从服务端通过客户端的内网地址连接
    • 连接后在服务端ssh连接客户端:
  2. DNS解析并不完美,在客户端apt-get更新源时有些链接无法解析: