2022.3.14更新

由于获取AS号的网站改了,脚本失效,所以有群友用Python重新写了一个从IPIP获取AS号,博客已经修改了教程

首先感谢各位大佬的教程,我只是站在巨人的肩膀上。

安装wireguard

手动安装

echo 'deb http://ftp.debian.org/debian buster-backports main' | sudo tee /etc/apt/sources.list.d/buster-backports.list

启用存储库后,更新apt缓存并安装WireGuard模块和工具:

sudo apt update
sudo apt install wireguard

WireGuard作为内核模块运行。

配置WireGuard

您可以使用wgwg-quick命令行工具配置和管理WireGuard界面。

WireGuard VPN网络中的每个设备都需要具有私钥和公钥。运行以下命令以生成密钥对:

wg genkey | sudo tee /etc/wireguard/privatekey | wg pubkey | sudo tee /etc/wireguard/publickey

文件在/etc/wireguard目录中生成。使用catless 命令查看文件的内容。私钥绝不应与任何人共享,并且应始终保持安全。

Wireguard还支持预共享密钥,这增加了对称密钥加密的附加层。该密钥是可选的,并且对于每个对等对必须唯一。

下一步是配置将路由VPN流量的隧道设备。

可以使用ipwg命令从命令行设置设备,也可以通过手动创建配置文件来设置设备。我们将使用文本编辑器创建配置。

打开您的编辑器并创建一个新文件wg0.conf,其名称如下:

sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
SaveConfig = true
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE

您可以为接口命名任何您想要的名称。但是,建议使用类似wg0或的东西wgvpn0

界面部分中的设置具有以下含义:

  • 地址-wg0接口的v4或v6 IP地址的逗号分隔列表。您可以为专用网络保留一个范围内的IP地址(10.0.0.0/8、172.16.0.0/12或192.168.0.0/16)。
  • ListenPort-侦听端口。
  • PrivateKey-wg genkey命令生成的私钥。(要查看的文件类型的内容:sudo cat /etc/wireguard/privatekey
  • SaveConfig-设置为true时,关闭时接口的当前状态将保存到配置文件中。
  • PostUp-在启动界面之前执行的命令或脚本。在此示例中,我们使用iptables启用伪装。这允许流量离开服务器,从而使VPN客户端可以访问Internet。
  • 请确保在ens3之后替换-A POSTROUTING以与您的公共网络接口的名称匹配。您可以通过以下方式轻松找到该接口:
ip -o -4 route show to default | awk '{print $5}'
  • PostDown-在关闭接口之前执行的命令或脚本。接口关闭后,iptables规则将被删除。

wg0.confprivatekey文件不应该是人类可读普通用户。用于chmod 将文件权限设置为600

sudo chmod 600 /etc/wireguard/{privatekey,wg0.conf}

完成后,wg0使用配置文件中指定的属性启动接口:

sudo wg-quick up wg0

输出将如下所示:

[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.0.0.1/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE

要检查接口状态和配置,请运行:

sudo wg show wg0
interface: wg0
  public key: +Vpyku+gjVJuXGR/OXXt6cmBKPdc06Qnm3hpRhMBtxs=
  private key: (hidden)
  listening port: 51820

您还可以使用以下命令验证接口状态ip a show wg0

ip a show wg0
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet 10.0.0.1/24 scope global wg0
       valid_lft forever preferred_lft forever

可以使用Systemd来管理WireGuard。要在启动时启用WireGuard接口,请运行以下命令:

sudo systemctl enable wg-quick@wg0

服务器网络和防火墙配置

必须启用IP转发才能使NAT正常工作。打开/etc/sysctl.conf文件并添加或取消注释以下行:

sudo nano /etc/sysctl.conf
net.ipv4.ip_forward=1

保存文件并应用更改:

sudo sysctl -p
net.ipv4.ip_forward = 1

如果您使用UFW管理防火墙 ,则需要在以下端口打开UDP流量51820

sudo ufw allow 51820/udp

脚本安装

脚本来自秋水逸冰

wget --no-check-certificate -O /opt/wireguard.sh https://raw.githubusercontent.com/teddysun/across/master/wireguard.sh
chmod 755 /opt/wireguard.sh

从代码编译安装 WireGuard

/opt/wireguard.sh -s

从 repository 直接安装 WireGuard

/opt/wireguard.sh -r

安装完成后,脚本提示如下

WireGuard VPN Server installation completed
WireGuard VPN default client file is below:
/etc/wireguard/wg0_client
WireGuard VPN default client QR Code is below:
/etc/wireguard/wg0_client.png
Download and scan this QR Code with your phone
Welcome to visit: https://teddysun.com/554.html
Enjoy it

卸载方法

/opt/wireguard.sh -n

其他使用选项

查看已安装 WireGuard 版本号

/opt/wireguard.sh -v

编译升级 WireGuard 到当前最新版本

/opt/wireguard.sh -u

新增 WireGuard 客户端配置

/opt/wireguard.sh -a

删除 WireGuard 客户端配置

注意:默认客户端 wg0 不允许删除

/opt/wireguard.sh -d

列出 WireGuard 客户端配置

/opt/wireguard.sh -l

高级用法

如果你在安装时,需要自定义自己想要的端口,那么可以 export 变量 VPN_SERVER_WG_PORT 的值,这样脚本就会读取这个变量值来定义监听端口,而不会自己随机生成。
比如你想自定义端口为 1234,那么具体做法就是,在执行从代码编译安装 WireGuard 或者从 repository 直接安装 WireGuard 之前,运行如下命令:

export VPN_SERVER_WG_PORT=1234

下面是一份脚本里用到的变量列表名(共计 11 个),以及它们具体代表什么含义的说明。
VPN_SERVER_PUB_IPV4,定义服务器公网 IPv4,如果你的服务器端存在多个可用公网 IPv4,指定此变量的值。
VPN_SERVER_PUB_IPV6,定义服务器公网 IPv6,如果你的服务器端存在多个可用公网 IPv6,指定此变量的值。
VPN_SERVER_PUB_NIC,定义服务器默认网卡名称,如果你的服务器有多个可用网卡,指定此变量的值。
VPN_SERVER_WG_NIC,定义 WireGuard 网卡名,默认为 wg0,这里一般不推荐指定此变量的值。
VPN_SERVER_WG_IPV4,定义 WireGuard 服务端的内网 IPv4,默认为 10.88.88.1,这里一般不推荐指定此变量的值。
VPN_SERVER_WG_IPV6,定义 WireGuard 服务端的内网 IPv6,默认为 fd88:88:88::1,这里一般不推荐指定此变量的值。
VPN_SERVER_WG_PORT,定义器 WireGuard 服务端的监听端口,默认为从 1024 到 20480 随机生成,如果你想自定义端口,指定此变量的值。
VPN_CLIENT_WG_IPV4,定义 WireGuard 默认客户端的内网 IPv4,默认为 10.88.88.2,这里一般不推荐指定此变量的值。
VPN_CLIENT_WG_IPV6,定义 WireGuard 默认客户端的内网 IPv6,默认为 fd88:88:88::2,这里一般不推荐指定此变量的值。
VPN_CLIENT_DNS_1,定义 WireGuard 默认客户端的 DNS,默认为 1.1.1.1,如果你想自定义为别的 DNS,指定此变量的值。
VPN_CLIENT_DNS_2,定义 WireGuard 默认客户端的 DNS,默认为 8.8.8.8,如果你想自定义为别的 DNS,指定此变量的值。

安装bird2

由于目前存在于Debian 10镜像库中的Bird版本仅为Bird1 (Bird 1.6.6),建议大家尽快升级到Bird2版本,以获取更多功能。

我们从官方下载最新版本的Bird组件:

wget -O bird2.deb https://bird.network.cz/download/debian/pool/main/b/bird2/bird2_2.0.7-2+0~20191023.15+debian10~1.gbp23b01f_amd64.deb

由于此版本Bird2安装包依赖 libssh-gcrypt-4 软件包,所以我们无法直接使用 dpkg -i 方式安装此软件。

但毕竟天无绝人之路,我们还是有两种办法安装Bird2。

第一种方法,是手动安装缺少的软件包,然后再安装Bird:

apt install libssh-gcrypt-4 -y
dpkg -i bird2.deb
systemctl enable bird.service

第二种方法,是让apt自动补全缺少的依赖包:

apt install ./bird2.deb -y
systemctl enable bird.service

配置wireguard

我是直接用的脚本生成的客户端,到/etc/wireguard下面打开客户端的配置文件

image.png

image.png

image.png

按照生成的客户端文件创建ROS的wireguard和peer

image.png

然后根据配置文件,给wireguard接口创建IP

配置bird

配置文件在/etc/bird

router id vultr的IP;

include "asn_cn.conf";

protocol device {}

protocol static {
        ipv4 {};
}

protocol bgp vultr
{
        local as vultr的AS;
        neighbor 169.254.169.254 as 64515;
        password "BGP密码";
        source address vultr的IP;

  ipv4 {
                import all;
                export none;
  };
        graceful restart on;
        multihop 2;

}

protocol bgp home
{
        local as 65533;
        neighbor 10.88.88.2 as 65532;
        source address 10.88.88.1;

  ipv4 {
                import none;
                export filter {
                        #if bgp_path ~ [4134, 4809, 36678, 4837, 9929, 9808, 9394, 4538, 23910] then accept; else reject;
                        if bgp_path ~ china_asn then accept; else reject;
                };
  };
}

建一个自动更新中国asn的python脚本ipip.py,bird配置里会用到,并设定时作业

# version :Python 3.7.3
import os
import re
import urllib.request


# 读出文件最后一行
# 参考大神代码https://blog.csdn.net/weixin_30632899/article/details/97566294
def getEndLing(name):
    with open(name, 'rb') as f:
        file_size = os.path.getsize(name)
        offset = -100
        # 文件字节大小为0则返回none
        if file_size == 0:
            return ''
        while True:
            # 判断offset是否大于文件字节数,是则读取所有行,并返回最后一行
            if abs(offset) >= file_size:
                f.seek(-file_size, 2)
                data1 = f.readlines()
                return data1[-1]
            # 游标移动倒数的字节数位置
            f.seek(offset, 2)
            data1 = f.readlines()
            # 判断读取到的行数,如果大于1则返回最后一行,否则扩大offset
            if len(data1) > 1:
                return data1[-1]
            else:
                offset *= 2


file_name = 'asn_cn.conf'
str1 = 'define china_asn = ['
str5 = '];'
datas_source = 'https://whois.ipip.net/countries/CN'

response = urllib.request.urlopen(datas_source)

html = response.read().decode('utf-8')

with open(file_name, 'a') as file:
    file.write(str1 + "\n")
print("step 1.添加文件第一行字符串!")

results = re.findall(', CN\">AS(.*?)</a> </td>', html, re.S)
for result in results:
    with open(file_name, 'a') as file_object:
        str2 = result.strip() + ',' + '\n'
        file_object.write(str2)
print("step 2.采集ASN号数据!")

data2 = getEndLing(file_name)
if data2:
    str3 = data2.decode('utf-8').strip()


with open(file_name,"r",encoding="utf-8") as f:
    lines = f.readlines()
    #print(lines)
with open(file_name,"w",encoding="utf-8") as f_w:
    for line in lines:
        if str3 in line:
            continue
        f_w.write(line)
print("step 3.提取数据完成!")

str4 = str3[:-1]
with open(file_name, 'a') as file:
    file.write(str4 + "\n")
    file.write(str5)

print("step 4.生成中国区ASN成功!")

安装python

apt update
apt install python3

然后创建一个执行的脚本update.sh

#!/bin/bash
cd /etc/bird
python ipip.py
birdc c
chmod +x update.sh

定时任务

crontab -e

选1

image.png

0 0 * * 0  /etc/bird/update.sh

执行脚本

./update.sh

查看是否建立链接

birdc show protocol all

网络设置进程

vultr上开机网络设置进程

cat > /etc/network-conf.sh <<-EOF
#!/bin/bash
common() {
      iptables -t filter -A ufw-user-input -p tcp --dport 51820 -j ACCEPT
      iptables -t filter -A ufw-user-input -p udp --dport 51820 -j ACCEPT
      iptables -t filter -A ufw-user-input -p tcp --dport 51819 -j ACCEPT
      iptables -t filter -A ufw-user-input -p udp --dport 51819 -j ACCEPT
      iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE; 
      iptables -t mangle -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
      iptables -t mangle -A OUTPUT -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
      
}
common &
sleep infinity
EOF
chmod +x /etc/network-conf.sh
cat > /etc/systemd/system/network-conf.service <<-EOF
[Unit]
Description=network conf service
After=network.target network-online.target nss-lookup.target
Wants=network-online.target
[Service]
ExecStart=/etc/network-conf.sh
Restart=on-failure
[Install]
WantedBy=default.target
EOF
systemctl enable network-conf.service
systemctl start network-conf.service

设置 ROS

版本ROS 7.1.1

配置BGP

image.png

chain填bgp rule(随意)

rule填

if (protocol bgp) {set gw pppoe-out1;accept}

image.png

添加table

image.png

  • name随便
  • AS 65532
  • RouterID 随便,我这里填的wireguard的地址
  • Remote Address 这里填vultr的wireguard的IP
  • Remote As 65533
  • Local Role 选择ebgp

image.png

  • Routing Table选择bgp(前面创建的)

image.png

  • Input Filter选择bgp rule

点击OK

image.png

然后点击sessions就可以看到vultr了

标记

创建地址列表,填入内网要科学上网的设备的IP
image.png

image.png

mangle里对内网ip的流量标记到bgp

image.png

image.png

image.png

image.png

因为bgp表里是中国路由,走pppoe拨号出去,因此要追加默认路由,从隧道出国

image.png

网关可以填 wireguard等隧道名。也可以像我这样填openwrt的地址

最后修改:2022 年 03 月 15 日
感谢您的支持