通过WireGuard搭建隧道实现内网穿透

1、安装wireguard

WireGuard 的安装条件非常苛刻,对内核版本要求极高,不仅如此,在不同的系统中,内核,内核源码包,内核头文件必须存在且这三者版本要一致,Red Hat、CentOS、Fedora 等系统的内核,内核源码包,内核头文件包名分别为 kernelkernel-develkernel-headers;Debian、Ubuntu 等系统的内核,内核源码包,内核头文件包名分别为 kernellinux-headers。果这三者任一条件不满足的话,则不管是从代码编译安装还是从 repository 直接安装,也只是安装了 wireguard-tools 而已。而 WireGuard 真正工作的部分,是 wireguard-dkms,也就是动态内核模块支持(DKMS),是它将 WireGuard 编译到系统内核中。

目前 WireGuard 已经被合并到 Linux 5.6 内核中了,如果你的内核版本 >= 5.6,就可以用上原生的 WireGuard 了,只需要安装 wireguard-tools 即可,内核版本<5.6,可能需要首先更新内核,否则可能会报错:Unable to access interface: Protocol not supported,如下为更新内核版本示例(CentOS)。

1) 升级内核

# 查看当前内核版本
uname --kernel-release

# 安装必要工具,卸载旧的内核源码包
yum -y install epel-release curl
sed -i "0,/enabled=0/s//enabled=1/" /etc/yum.repos.d/epel.repo
yum remove -y kernel-devel

# 导入公钥
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# 升级安装 elrepo
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
# 安装新版本工具包
yum --disablerepo="*" --enablerepo="elrepo-kernel" list available
yum -y --enablerepo=elrepo-kernel install kernel-ml
# 设置默认启动
sed -i "s/GRUB_DEFAULT=saved/GRUB_DEFAULT=0/" /etc/default/grub
grub2-mkconfig -o /boot/grub2/grub.cfg
wget https://elrepo.org/linux/kernel/el7/x86_64/RPMS/kernel-ml-devel-5.15.10-1.el7.elrepo.x86_64.rpm
rpm -ivh kernel-ml-devel-5.15.10-1.el7.elrepo.x86_64.rpm
yum -y --enablerepo=elrepo-kernel install kernel-ml-devel

# 重启
reboot

# 查看升级后的内核版本
uname --kernel-release

2) 安装wireguard

通过官网方法安装
Method 1: a signed module is available as built-in to CentOS's kernel-plus:

$ sudo yum install yum-utils epel-release
$ sudo yum-config-manager --setopt=centosplus.includepkgs=kernel-plus --enablerepo=centosplus --save
$ sudo sed -e 's/^DEFAULTKERNEL=kernel$/DEFAULTKERNEL=kernel-plus/' -i /etc/sysconfig/kernel
$ sudo yum install kernel-plus wireguard-tools
$ sudo reboot
Method 2: users wishing to stick with the standard kernel may use ELRepo's pre-built module:

$ sudo yum install epel-release elrepo-release
$ sudo yum install yum-plugin-elrepo
$ sudo yum install kmod-wireguard wireguard-tools
Method 3: users running non-standard kernels may wish to use the DKMS package instead:

$ sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
$ sudo curl -o /etc/yum.repos.d/jdoss-wireguard-epel-7.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-7/jdoss-wireguard-epel-7.repo
$ sudo yum install wireguard-dkms wireguard-tools
docker安装
docker pull linuxserver/wireguard
docker run -itd --entrypoint=bash \
  --name=wg \
  --cap-add=NET_ADMIN \
  --cap-add=SYS_MODULE \
  -e PUID=1000 \
  -e PGID=1000 \
  -v /lib/modules:/lib/modules \
  --sysctl="net.ipv4.conf.all.src_valid_mark=1" \
  linuxserver/wireguard 

2、利用公网机器对nat设备下机器点对点建立隧道

在wiregaurd中,节点之间是不区分服务端与客户端的,统一概念为peer。谁发起连接谁就是客户端,因此客户端需要配置endpoint。

建立以下图为示的隧道,使公网机器peer2能通过隧道访问到家庭局域网内的peer1。

利用公网机器对nat设备下机器点对点建立隧道

1) 公私钥生成

通过以下命令生成peer1和peer2公私钥。

# 生成公私钥到wg-pubkey和wg-prikey下。
wg genkey | tee wg1-prikey | wg pubkey > wg1-pubkey
wg genkey | tee wg2-prikey | wg pubkey > wg2-pubkey

2) 编写配置文件

生成peer1和peer2的wiregurad配置文件

# 分别赋值
WG1_PRIKEY=`cat wg1-prikey`
WG1_PUBKEY=`cat wg1-pubkey`
WG2_PRIKEY=`cat wg2-prikey`
WG2_PUBKEY=`cat wg2-pubkey`
# 此例中以wg1作为服务端,所以endpoint配置成wg1的
WG1_IP=<peer1的公网ip>
WG1_PORT=<peer1监听端口>

# peer1的wireguard配置生成
cat > wg1.conf<<EOF
[Interface]
Address = 5.5.5.2/24
PrivateKey = ${WG2_PRIKEY}

[Peer]
PublicKey = ${WG1_PUBKEY}
Endpoint = ${WG1_IP}:${WG1_PORT}
AllowedIPs = 5.5.5.1/32
PersistentKeepalive = 15
EOF

#peer2的wireguard配置生成
cat > wg2.conf<<EOF
[Interface]
Address = 5.5.5.1/24
ListenPort = ${WG1_PORT}
PrivateKey = ${WG1_PRIKEY}

[Peer]
PublicKey = ${WG2_PUBKEY}
AllowedIPs = 5.5.5.2/32
EOF

参考生成配置如下

# peer1
[Interface]
Address = 5.5.5.2/24
PrivateKey = OHHeTtRg4kk3SFyxxbWJVlWO31y6xfD51OWQAQlwc2k=
[Peer]
PublicKey = GcKpj9v2kUojkHV3fgecW4VUzIgzD6HSoH2tCD7DOaTQ=
Endpoint = 172.0.0.2:10240
AllowedIPs = 5.5.5.1/32
# 每隔15s发送一个keepalive数据包
# PersistentKeepalive参数用于保持链接的存活,默认情况下wireguard在不使用的情况下尽量少发送数据包,但是在对于位于NAT后的peer1来讲,其公网地址随时都在变化,所以我们希望通过定时发送存活包让peer2知晓peer1的公网地址与对应的端口,保持链接的存活性,这就是所谓的IP漫游。
PersistentKeepalive = 15
# peer2
[Interface]
Address = 5.5.5.1/24
ListenPort = 10240
PrivateKey = SOSEvKhRG+7b0Ag9sqiRDOW9V10q3KEY+x3gMloh124=
[Peer]
PublicKey = SHZ2K6oIVSTdtPld3i7zJnXKOrKAwk1ynMn1mry5CF0=
AllowedIPs = 5.5.5.2/32

3) 启动服务

将生成配置文件分别拷贝到两台机器上。

# 将配置文件拷贝到 /etc/wireguard 目录下。
cp wg1.conf /etc/wireguard

#启动
wg-quick up wg1

# 输出以下结果为启动成功
# 出现Unable to access interface: Protocol not supported 则内核未升级
#[#] ip link add wg1 type wireguard
#[#] wg setconf wg1 /dev/fd/63
#[#] ip -4 address add 5.5.5.1/24 dev wg1
#[#] ip link set mtu 1420 up dev wg1

# wg2操作相同

此时,首先要在peer1去ping通peer2后,peer2才能与peer1通行,因为需要由peer1根据endpoint进行隧道建立。此时简单的点对点隧道搭建完成。

3、在点对点基础上进行内网转发

建立以下图为示的隧道,使公网机器peer2能像在peer1局域网内一样,访问内网服务。

在点对点基础上进行内网转发

其中只对peer1的配置中添加了关于iptables的内网转发规则。实际上是将来自wiregurad的流量到输出到网卡进行转发。关于iptables可以了解一下其五链四表和一些常用的规则

1) 配置变化

  • peer1需要添加路由转发规则

    # peer1
    [Interface]
    Address = 5.5.5.2/24
    # 启动时添加路由规则
    PostUp   = iptables -A FORWARD -i %i -j ACCEPT
    PostUp   = iptables -A FORWARD -o %i -j ACCEPT
    PostUp   = iptables -t nat -A POSTROUTING -o <网卡名称> -j MASQUERADE
    # 停止时删除路由规则
    PostDown = iptables -D FORWARD -i %i -j ACCEPT
    PostDown = iptables -D FORWARD -o %i -j ACCEPT
    PostDown = iptables -t nat -D POSTROUTING -o <网卡名称> -j MASQUERADE
    
    PrivateKey = OHHeTtRg4kk3SFyxxbWJVlWO31y6xfD51OWQAQlwc2k=
    [Peer]
    PublicKey = GcKpj9v2kUojkHV3fgecW4VUzIgzD6HSoH2tCD7DOaTQ=
    Endpoint = 172.0.0.2:10240
    AllowedIPs = 5.5.5.1/32
    # 每隔15s发送一个keepalive数据包
    # PersistentKeepalive参数用于保持链接的存活,默认情况下wireguard在不使用的情况下尽量少发送数据包,但是在对于位于NAT后的peer1来讲,其公网地址随时都在变化,所以我们希望通过定时发送存活包让peer2知晓peer1的公网地址与对应的端口,保持链接的存活性,这就是所谓的IP漫游。
    PersistentKeepalive = 15
    
  • peer2需要添加peer配置中的allowIps

    [Peer]
    PublicKey = SHZ2K6oIVSTdtPld3i7zJnXKOrKAwk1ynMn1mry5CF0=
    AllowedIPs = 5.5.5.2/32,192.168.1.0/24
    PersistentKeepalive = 15
    

重新启动wg,再使用peer2去访问192.168.1.151即可。

4、公网机器充当中转机(最终实现)

注意,应该先看直连方案后在看中转方案,中转方案是基于直连方案之上的。且对wireguard配置文件有一定了解。

在现实情况中更多的场景是中转,如两台设备都处于NAT中,一台设备需要访问另外一台设备所处的内网,假设是peer1,peer2仍然是处于公网中的主机,peer3则是需要访问peer1中内网服务的主机,如下图所示:

公网机器充当中转机(最终实现)

peer3访问peer1的方式,就类似于我们windows办公机器需要通过公网机器中转到我们nat网络中。即我想要在外面通过笔记本电脑访问家里的非公网机器。

1) 配置变化

  • peer1相较前篇无配置变化

  • peer2

    • 新增[peer]标签,代表新增peer3,填入对应peer3的公钥和ip地址即可。

    • 添加路由转发,与peer1的转发不同,该流量是从wg隧道输入,又从wg输出。

      PostUp   = iptables -A FORWARD -i %i -j ACCEPT
      PostUp   = iptables -A FORWARD -o %i -j ACCEPT
      PostUp   = iptables -t nat -A POSTROUTING -o %i -j MASQUERADE
      PostDown = iptables -D FORWARD -i %i -j ACCEPT
      PostDown = iptables -D FORWARD -o %i -j ACCEPT
      PostDown = iptables -t nat -D POSTROUTING -o %i -j MASQUERADE
      
  • peer3配置peer1相似,在原有基础上去除转发即可。

peer3编写完成后,通过windows端wireguard导入配置,启动后即可访问到192.168.1.151

2) 最终所有配置文件

  • peer1

    [Interface]
    Address = 5.5.5.2/24
    PostUp   = iptables -A FORWARD -i %i -j ACCEPT
    PostUp   = iptables -A FORWARD -o %i -j ACCEPT
    PostUp   = iptables -t nat -A POSTROUTING -o ens192 -j MASQUERADE
    PostDown = iptables -D FORWARD -i %i -j ACCEPT
    PostDown = iptables -D FORWARD -o %i -j ACCEPT
    PostDown = iptables -t nat -D POSTROUTING -o ens192 -j MASQUERADE
    PrivateKey = OHHeTtRg4kk3SFyQAQlwc2k=
    
    [Peer]
    PublicKey = GcKpj9v2kUojkHV3fgecW4VUQ=
    Endpoint = <ip>:<port>
    AllowedIPs = 5.5.5.1/32
    PersistentKeepalive = 15
    
  • peer2

    [Interface]
    Address = 5.5.5.1/24
    PostUp   = iptables -A FORWARD -i %i -j ACCEPT
    PostUp   = iptables -A FORWARD -o %i -j ACCEPT
    PostUp   = iptables -t nat -A POSTROUTING -o %i -j MASQUERADE
    PostDown = iptables -D FORWARD -i %i -j ACCEPT
    PostDown = iptables -D FORWARD -o %i -j ACCEPT
    PostDown = iptables -t nat -D POSTROUTING -o %i -j MASQUERADE
    ListenPort = 10240
    PrivateKey = SOSEvKhR10q3KEY+xzgMlohV24=
    
    [Peer]
    PublicKey = SHZEK6oIVSTdtPldnsmry5CF0=
    AllowedIPs = 5.5.5.2/32,192.168.1.0/24
    PersistentKeepalive = 15
    
    [Peer]
    PublicKey = O1TBQKHWeBhc7sHuzcFi9EmH0=
    AllowedIPs = 5.5.5.3/32
    PersistentKeepalive = 15
    
  • peer3

    [Interface]
    PrivateKey = qCiw7PPXkYxwOIsF+0N6vVs=
    Address = 5.5.5.3/24
    
    [Peer]
    PublicKey = GcKpj9v2kUojkHV3HtCD7DOaTQ=
    AllowedIPs = 5.5.5.0/24, 192.168.1.0/24
    Endpoint = <ip>:<port>
    PersistentKeepalive = 15
    

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354