美文网首页网络知识
通过WireGuard搭建隧道实现内网穿透

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

作者: 鸡龙 | 来源:发表于2022-08-19 23:25 被阅读0次

    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
      

    参考

    相关文章

      网友评论

        本文标题:通过WireGuard搭建隧道实现内网穿透

        本文链接:https://www.haomeiwen.com/subject/ipomgrtx.html