在外优雅访问家庭内网服务的姿势

dhuzbb · 2024-9-22 21:37:48 · 188 次点击
# 在外优雅访问家庭内网服务的姿势

## 前情提要

[《低成本家庭万兆内网搭建指北》]( https://www.fshex.com/t/1057803)  
[《个人家庭网络布局分享》]( https://www.fshex.com/t/1074592)  
[《家庭内网服务分享》]( https://www.fshex.com/t/1074688)  
[《局域网内优雅的访问家庭内网服务》]( https://www.fshex.com/t/1074771)  

## 起源

前面的文章中讲到了如何搭建内网服务,以及如何通过内网 DNS 重写并结合子域名以及个人服务导航页来优雅的访问局域网内搭建的各种服务。

很多小伙伴还是对在外远程访问家庭内网服务有很大需求的,下面就来讲解一下,我个人认为的比较不错的方式。

## 安全原则

远程访问家庭内网服务的原则只有一个,那就是安全性。

五星上将麦克阿瑟曾经说过:**不要为了方便而将内网服务直接暴露在公网上,那相当于在裸奔。**


## 选择的原因

所有第三方的远程访问服务个人都不推荐。主要从速度、安全性、便捷性三个方面考虑如下:

1. 速度方面:cloudflare 、tailscale 、zerotier 、frp 、蒲公英等所有需要第三方服务器中转的,速度都不太行。
2. 安全性方面:数据经过了第三方服务安全性无法得到保障。
3. 便捷性方面:最好能和在家里访问家里的局域网服务一样。或者能够一键连接访问家里的网络。

我自己亲自实践过 cloudflare 、tailscale 、frp 等等很多的方案。最后觉得最理想的方案还是:公网 IP + DDNS + Wireguard 。

这个方案是如何保证上述三点的呢?

1. 速度方面。公网 IP 属于直连,比所有第三方服务都要快。能够完美的跑满家里的上传带宽。
2. 安全性方面。不经过任何的第三方服务,且 wireguard 是开源软件,安全性有保障。
3. 便捷性方面。可以将 wireguard 理解为一个 VPN 服务。一键即可连回家庭网络。和在家里访问家里局域网一样没有任何区别,不用改变自己的使用习惯。

**此外,上面的方案还带来了一个额外的优势,如果家里部署了科学上网服务,可以在外无缝使用家里的科学上网服务。**

## 实现步骤

下面以公网 ipv4 作为演示。搞懂了原理,公网 ipv6 其实也是一样的道理,B 站有大佬发过 ipv6 的视频,这里就不在赘述了。

### 前提条件

+ 具备公网 ipv4 或者 ipv6 。
+ 光猫最好桥接,路由器直接拨号上网。这样路由器上获取的 IP 直接就是公网 ipv4 或 ipv6 。

光猫桥接其实不是必须的,只是为了操作更加的简单。不过个人还是强烈建议光猫改桥接路由器直接拨号的模式,这样可以省去光猫后台设置端口转发到主路由的步骤。

### 步骤 1:动态域名解析

具备了公网 IP 后,还存在着一个问题,那就是这个公网 IP 会随着拨号设备的每次重启而变化。即使拨号设备一直不重启,过一段时间后这个公网 IP 还是会变化的。

所以需要 DDNS 动态域名解析服务来解决上面的问题,个人比较推荐 DDNS-GO 这个开源项目。

既可以采用 Docker 部署的方式,iStoreOS 的应用商店中也有这个插件,安装部署非常的方便。

```java
https://github.com/jeessy2/ddns-go
```

DNS 解析服务商选择国内的阿里、腾讯或者国外的 cloudflare 都没有问题(个人还是比较推荐互联网大善人 cloudflare )。

一个可有可无的小 Tip:DDNS-GO 可以设置 Webhook 通知,当你家里的公网 IP 变化了,可以直接微信通知你。

```java
URL:
https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxx

Request Body:
{
    "msgtype": "text",
    "text": {
        "content": "公网 IP 变更:\n 新 IPV4 地址:#{ipv4Addr} \n 已解析的域名:#{ipv4Domains} \n 域名更新结果:#{ipv4Result}"
    }
}
```

上面 key 的获取可以参考 DDNS-GO 项目文档中的 Webhook 配置参考,个人比较推荐微信通知的方式,通过企业微信的个人团队来获取 key 。

通知的效果如下:

![微信通知]( https://img.binhome.cn/remote_access/notify.png)


### 步骤 2:部署 Wireguard

虽然 Wireguard 在 iStoreOS ( OpenWRT )下有对应的插件,个人还是比较推荐采用 Docker 的方式来部署 Wireguard 。

Wireguard Docker 项目地址如下:

```java
https://github.com/wg-easy/wg-easy
```

Wireguard Docker 部署命令如下:

```java
docker run -d \
  --name=wg-easy \
  -e LANG=chs \
  -e WG_HOST=binhome.cn \
  -e WG_DEFAULT_DNS=192.168.0.2 \
  -e WG_PERSISTENT_KEEPALIVE=25 \
  -e PORT=51821 \
  -e WG_PORT=51820 \
  -v ~/.wg-easy:/etc/wireguard \
  -p 51820:51820/udp \
  -p 51821:51821/tcp \
  --cap-add=NET_ADMIN \
  --cap-add=SYS_MODULE \
  --sysctl="net.ipv4.conf.all.src_valid_mark=1" \
  --sysctl="net.ipv4.ip_forward=1" \
  --restart unless-stopped \
  ghcr.io/wg-easy/wg-easy
```   

+ 需要将 `WG_HOST` 中的域名替换为你自己的域名
+ 需要将 `WG_DEFAULT_DNS` 替换为你自己的内网 DNS 服务器。

最新版本的 wg-easy 修改了密码生成的方式,如果 Wireguard 的管理后台需要密码进行保护,可以这样做:

```java
# 使用下面的 Docker 命令生成密码 Hash
docker run -it ghcr.io/wg-easy/wg-easy wgpw 你的密码

# 然后在上面的 Docker 执行命令中添加一条密码配置(记住密码前后需要有单引号):
-e PASSWORD_HASH='上面生成的密码' \
```

Android 、iOS 、Mac 等等各大平台都有对应的客户端软件,大家自行下载安装。

Wireguard 的使用比较简单:wg-easy 的管理后台为需要远程访问的机器生成一个配置,客户端扫码进行连接即可。详细的步骤就不再演示了。

如果是在主路由上安装的 Wireguard ,通过上面简单的 2 步就已经可以实现远程访问的需求了。


### 步骤 3:设置端口转发

Docker 部署 Wireguard 既可以在主路由上,也可以在旁路由上。我个人是在旁路由上安装的 Wireguard ,所以多了第三步:还需要在主路由上设置端口转发到旁路由。

iStoreOS ( OpenWRT )的端口转发设置路径:网络 -> 防火墙 -> 端口转发。

![防火墙]( https://img.binhome.cn/remote_access/firewall.png)

添加一条端口转发:将外部端口 51820 的 UDP 协议转发到内部旁路由( 192.168.0.2 )的 51820 端口去。

![端口转发]( https://img.binhome.cn/remote_access/port_sent.png)

## 实现效果

下面演示一下手机远程连接的效果:

![远程访问]( https://img.binhome.cn/remote_access/homepage.png)

旁路由部署附带的另外一个好处就是,如果家里的旁路由部署了科学上网服务,在外手机可以无缝享受到科学上网的环境:

![科学上网]( https://img.binhome.cn/remote_access/search_google.png)


## 分析总结

从始至终,只在主路由上对外暴露了一个 Wireguard 的 UDP 协议的连接端口,没有对外暴露任何的内网服务,别人想扫描爆破密码都没可能。

整个原理和流程如下:

+ 由于具有公网 IP 并且设置了 DDNS ,所以在外访问 `binhome.cn` 就相当于直接访问家里的主路由。
+ 手机客户端通过 `binhome.cn:51820` 的 UDP 协议来连接家里的主路由。
+ 主路由将 51820 端口的 UDP 数据全部转发到旁路由( 192.168.0.2 )的 Wireguard 监听端口 51820 。

因此,上面就完成了远程回家的步骤。

在手机上内网子域名也能正常访问的原因在于:Wireguard 的配置中 `-e WG_DEFAULT_DNS=192.168.0.2` 指定了 DNS 服务器的 IP 。

手机客户端能够无缝科学上网的原因在于:默认情况下所有流量都会走 Wireguard 的接口,并且在旁路由上部署了科学上网服务。

![Wireguard APP 设置]( https://img.binhome.cn/remote_access/setting_wireguard.png)

Mac 电脑上的配置也是一样的,可以修改为只有家里的局域网段走 Wireguard 的接口。

![Wireguard Mac 设置]( https://img.binhome.cn/remote_access/wireguard_mac.png)

这样当 Mac 电脑在公司 24 小时连接家庭网络的时候,可以避免公司内网环境无法访问的问题。
举报· 188 次点击
登录 注册 站外分享
12 条回复  
ztm0929 小成 2024-9-22 21:48:05
这里面的 Wireguard 与 Nginx 之类的 Web 反向代理服务器有什么区别?它们的安全性是一样的吗?
kur0d3s 小成 2024-9-23 09:48:38
tailscale 可以自建控制器 headscale
zzzyk 小成 2024-9-23 11:00:57
羡慕有公网 ip 的
stefwoo 小成 2024-9-23 11:08:35
电信可以打电话找社区服务员找公网 ipv4 。ipv6 的话,好像三大运营商都自带。
jwz426 小成 2024-9-23 11:12:43
使用 wg-easy 如果想实现异地多个 LAN 互联的话,感觉没有直接用 OpenWrt 的 wireguard 方便。
coolcoffee 小成 2024-9-23 17:19:41
都有公网 IP 了,tailscale 、zerotier 这类 P2P 组网是大概率可以直连的,中转服务器只是用来前期握手而已。

wireguard 原生的很大弊端就是如果宽带发生了重拨导致 ip 变更,免费版本的 DNS 缓存更新就是 5 分钟起步,急用的时候都是手动设置 ip 去连接,而且以前还遇到过客户端连接时间久了需要手动重连才能生效。这个要是对于长时间的远端异地组网是致命的。

人生苦短,我选择 tailscale🐶
relsoul 小成 2024-9-23 17:33:07
不赞同 lz 的组网方案,我个人的建议是走 tailscale+自建中转站。

19 年自己已经写过对应的阿里云脚本,走的定时器查询+阿里云 api 改 dns ,这里会有几个问题
1. 阿里云的个人版 dns 解析不会那么及时生效(具体生效时间随缘),甚至你需要先 del 原有的解析记录再 add
2. 公网 ip 随时会变,并且这个频率不会太低,尤其是当你有外网端口访问进来的时候,可能会导致上一秒能访问,下一秒 ip 就变了,目前除非是固定公网 ip ,这种动态公网 ip 就在挑战如何触发运营商的风控机制。

至于 Wireguard ,用了 tailscale 的体验会比单纯搭建 Wireguard 会好很多。

nps ,cloudflare  zero ,基本上都用过,体验最好的还是 tailscale 。
swordspoet 小成 2024-9-23 18:21:06
我是用的 ipv6 ,只是需要公网支持 ipv6 才能访问家里的服务。
lovepocky 小成 2024-9-23 19:33:39
你这都有公网 v4 了,可选方案多到数不清
12下一页
返回顶部