Solution for Internet Connection Sharing Broken after Reboot on Windows 10

Notice

This is an old article and only available in Chinese. If you need a translation, please leave a comment and I will do my best to provide it as soon as possible.

2020-02-25 更新:

今天在某 Telegram 群里摸鱼的时候又扯到了这个话题,群友提出了更科学的解决方法,直接修改注册表让 Windows 启用持续化的网络连接共享,具体来说就是创建一个注册表项:

1
2
3
4
Path: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\SharedAccess
Type: DWORD
Setting: EnableRebootPersistConnection
Value: 1

值得注意的是,这个方法只可以在 Windows 10 1709 以上,且安装了 KB 4054517 更新的计算机上生效,具体可以查看微软的文档:ICS doesn’t work after computer or service restart on Windows 10


在上海租的房子只提供了无线接入(802.11n)的方式来访问互联网,而我个人又比较希望自己能获得一个更快的无线内网,并把自己的网络设备对外部隐藏,所以我就购入了一个 NETGEAR A6210 的无线网卡,支持 802.11AC,USB 3.0 界面,准备做一个这样的网络连接:

1
2
3
4
5
6
7
8
9
+--------------------+       +-----------------------+
| LAN(802.11AC + GbE)| CAT5E |  HP ProLiant MS Gen8  |
| (PS4, Kindle, etc) +-------+  eth0: 192.168.137.1  |
|  192.168.137.0/24  |       | wlan0: 192.168.0.x/24 |
+--------------------+       +---+-------------------+
                                 | 802.11n
                             +---+------------+
                             | TP-LINK Router |
                             +----------------+

这种结构对于 Linux PC 来说十分简单,只需要开启 ip_forward 并执行 iptables -t nat -A POSTROUTING -j MASQUERADE 就能做到,但是可惜这块 USB3.0 的无线网卡主线内核里并没有驱动,MTK 开源的驱动在 OpenWrt 下性能又非常糟糕,无奈只能选择使用 Windows 来做路由。

本来呢对于 Windows 来说配置这样的网络也很简单,右击无线网卡的适配器选择共享网络连接就好了,然而万恶的微软在网络共享的实现上埋了个 bug:重启电脑后网络共享会失效,表现为被共享的接口仍然能提供 DHCP 服务,但是 IP Forward 却完全不可用。进入网络连接,取消共享后再执行一次共享,问题就能解决。

那么我们只需要准备一个计划任务让系统每次开机都重复一遍这个操作就 OK 了,写一段 PowerShell 脚本即可:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
$NetShare = New-Object -ComObject HNetCfg.HNetShare
$wlan = $null
$ethernet = $null

foreach ($int in $NetShare.EnumEveryConnection) {
  $props = $NetShare.NetConnectionProps.Invoke($int)
  if ($props.Name -eq "WLAN") {
    $wlan = $int;
  }
  if ($props.Name -eq "网桥") {
    $ethernet = $int;
  }
}

$wlanConfig = $NetShare.INetSharingConfigurationForINetConnection.Invoke($wlan);
$ethernetConfig = $NetShare.INetSharingConfigurationForINetConnection.Invoke($ethernet);

$wlanConfig.DisableSharing();
$ethernetConfig.DisableSharing();

$wlanConfig.EnableSharing(0);
$ethernetConfig.EnableSharing(1);

参考资料

  1. NetConnectionSharing (PowerShell Module)
comments powered by Disqus
Except where otherwise noted, content on this blog is licensed under CC-BY 2.0.
Built with Hugo
Theme Stack designed by Jimmy