使用WireGuard和云服务器实现内网穿透SSH

前言

  • 本文目标: 讲解如何使用一台具有公网IP的云服务器和WireGuard,搭建一个安全的虚拟局域网,从而实现从外网通过SSH直接访问处于内网(NAT后)的Ubuntu主机。

环境准备

在开始配置前,请确认你的环境符合以下描述:

  • 云服务器: 1核 CPU, 8GB 内存, 100Mbps 带宽, 搭载 Ubuntu 24 操作系统,并拥有一个固定的公网IP。
  • 局域网主机: 一台位于NAT网络后的Ubuntu 22主机。
  • 需求: 配置内网穿透,以便能通过云服务器远程SSH访问局域网的Ubuntu主机。

安装与配置 WireGuard

WireGuard的配置分为两部分:云服务器作为服务端,局域网主机作为客户端。

云服务器端 (Server) 配置

  1. 安装 WireGuard:

    1
    2
    sudo apt update
    sudo apt install wireguard
  2. 生成密钥对:
    密钥是WireGuard安全性的核心。

    1
    2
    3
    4
    sudo mkdir -p /etc/wireguard
    sudo chmod 755 /etc/wireguard
    cd /etc/wireguard
    sudo wg genkey | sudo tee privatekey | sudo wg pubkey | sudo tee publickey

提示: privatekey是私钥(绝不外泄),publickey是公钥(用于交换)。

  1. 创建配置文件:

    1
    sudo nano /etc/wireguard/wg0.conf
  2. 写入配置:
    将以下内容粘贴至 wg0.conf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [Interface]
    # 云服务器的配置
    PrivateKey = <粘贴云服务器的privatekey内容>
    Address = 10.0.0.1/24
    ListenPort = 51820

    [Peer]
    # 来自局域网客户端的配置
    PublicKey = <粘贴局域网Ubuntu的publickey内容>
    AllowedIPs = 10.0.0.2/32
    • 注意: PrivateKeyPublicKey 需要在后续步骤中获取并替换。AllowedIPs 指定了允许通过隧道的IP地址。
  3. 开启IP转发:
    要让云服务器能转发数据包,需要开启内核的IP转发功能。

    1
    sudo nano /etc/sysctl.conf

​ 找到并取消注释 (或添加) net.ipv4.ip_forward=1 这一行,然后执行 sudo sysctl -p 使其生效。


局域网主机端 (Client) 配置

  1. 安装 WireGuard:

    1
    2
    sudo apt update
    sudo apt install wireguard
  2. 生成密钥对:
    与服务器端操作相同,为客户端生成独立的密钥。

    1
    2
    3
    4
    sudo mkdir -p /etc/wireguard
    sudo chmod 755 /etc/wireguard
    cd /etc/wireguard
    sudo wg genkey | sudo tee privatekey | sudo wg pubkey | sudo tee publickey
  3. 创建配置文件:

    1
    sudo nano /etc/wireguard/wg0.conf
  4. 写入配置:
    将以下内容粘贴至 wg0.conf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [Interface]
    # 局域网Ubuntu的配置
    PrivateKey = <粘贴局域网Ubuntu的privatekey内容>
    Address = 10.0.0.2/24

    [Peer]
    # 指向云服务器的配置
    PublicKey = <粘贴云服务器的publickey内容>
    Endpoint = <云服务器公网IP>:51820
    AllowedIPs = 10.0.0.0/24
    PersistentKeepalive = 25
    • 注意: Endpoint 必须是云服务器的公网IP和监听端口。PersistentKeepalive 用于保持NAT会话,防止连接中断。

设置安全权限

为保证密钥安全,在 两台机器上 都执行以下命令,限制对配置和密钥文件的访问权限。

1
2
sudo chmod 600 /etc/wireguard/privatekey
sudo chmod 600 /etc/wireguard/wg0.conf

启动、测试与开机自启

  1. 配置云服务器防火墙/安全组:
    在你的云服务商控制台中,确保防火墙或安全组开放了以下端口:

    • UDP 51820: 用于WireGuard的通信。

    • TCP 22: 用于SSH访问。

  2. 启动WireGuard服务:
    两台机器上 都执行以下命令来启动wg0接口。

    1
    sudo wg-quick up wg0
  3. 设置开机自启:
    为了确保重启后服务能自动运行,在 两台机器上 都执行:

    1
    sudo systemctl enable wg-quick@wg0
  4. 连通性测试:

    • 检查状态: 使用 sudo wgsudo wg show 命令查看接口状态和最新的握手信息。

    • Ping 测试:

      1
      2
      3
      4
      5
      # 在云服务器上
      ping 10.0.0.2

      # 在局域网主机上
      ping 10.0.0.1

      如果双方都能ping通,说明WireGuard隧道已成功建立。

  5. SSH 访问测试:
    现在,你应该可以在云服务器上,通过WireGuard分配的内部IP直接访问局域网主机了。

    1
    2
    # 在云服务器上执行
    ssh <局域网主机的用户名>@10.0.0.2

配置SSH客户端隧道 (以FinalShell为例)

为了能从你自己的电脑直接连接到局域网主机,可以利用云服务器作为跳板机设置SSH隧道。

  1. 配置SSH隧道:

    • 首先,确保你本地的SSH客户端(如FinalShell)已经配置好并能成功连接到 云服务器

    • 在FinalShell中,找到SSH连接的“隧道”或“端口转发”设置。

    • 创建一个新的 本地端口转发 规则:

      • 名称: 自定义,如 tunnel-to-lan
        • 类型/方向: 本地 (Local)
        • 监听地址/IP: 127.0.0.1 (绑定本机)
        • 监听端口: 10088 (或你本地任意未被占用的端口)
        • 目标地址/IP: 10.0.0.2 (局域网主机的WireGuard IP)
        • 目标端口: 22 (局域网主机的SSH服务端口)
  2. 连接局域网主机:

    • 保存隧道配置后,首先连接到你的云服务器,这将激活隧道。

      • 在FinalShell中新建一个SSH连接配置:
        • 主机/IP: 127.0.0.1
        • 端口: 10088 (即上一步设置的本地监听端口)
        • 用户名/密码: 局域网Ubuntu主机的用户名和密码。
    • 现在连接这个新配置,流量将通过 本机:10088 -> 云服务器 -> 局域网主机:22 的路径转发,实现无缝访问。


常见问题排查

  • 问题1: WireGuard突然无法连接。

    • 现象: 之前配置正常,但突然无法ping通或SSH。
    • 解决方法: 在两台机器上依次重启WireGuard服务。
      1
      2
      sudo wg-quick down wg0
      sudo wg-quick up wg0
  • 问题2: 生成密钥时出现 Warning: writing to world accessible file

    • 现象: 创建的密钥文件权限过于开放,存在安全风险。
    • 解决方法: 使用 umask 命令在创建文件前设置默认权限。
      1
      2
      3
      4
      cd /etc/wireguard
      rm privatekey publickey # 删除旧文件
      umask 077
      wg genkey | tee privatekey | wg pubkey | tee publickey