win8.1的hosts文件无故失效!

匿名
2014-06-03T19:41:42+00:00

我的Hosts文件之前都可以正常使用的,但是最近不知何故突然失效了。

如图,给大家做个演示测试:

可见hosts文件路径是对的,而且只有一行映射,确保没有其他的干扰项。

使用ipconfig /flushdns清理DNS缓存,而且其实我还停止了DNS Client服务的。然后继续ping,依然返回的是真实DNS解析的地址。

如图,可见system的权限也是有分配的。下面那个我自己的账户和Admin组的账户的权限也是完全控制的。

情况就是这样,不知为何最近突然失效了。我可能是遇到什么劫持了么?

上网找了一通,解决办法都没有用,不知究竟是什么原因呢?


我是分割线,解决办法在14楼我自己的回复里,因为不能标记自己的回复为解答,所以贴上来了


您好!

其实我这些天一直在试图找到一个办法,来检测windows是否成功读取到了hosts文件。因为现在的情况,非常像windows本身漠视了hosts文件的存在(但是我的确没有弄错路径)。所以如果能有个办法来检测到windows是否成功读取了hosts文件就好了。

我在想,windows是否会缓存hosts文件,这样的话,内存中应该有个hosts文件的副本,那可能有某种途径能读取这片内存空间,看看内容是否和实际hosts文件的内容对应即可判断是否成功读取了。

如果windows不缓存hosts文件,而是直接每次请求一次DNS解释就打开一次hosts文件检测是否有对应映射的话,那应该也可以有个办法检测到windows是否有触动hosts文件,是否触动成功等。比如是否会产生一些消息记录?

苦于没有找到相应的检测办法,所以不知您是否有一些高见?

非常感谢这些天来 王小石 和 John Wu 的倾力帮助,给了很多很有帮助的提示!

现在问题已经被我自己解决掉了,公布如下:

根据引用中我的猜想,我使用了消息记录器来跟踪与hosts文件有关的系统消息。为了对比,我同时在windows 8.1和虚拟机中运行的windows XP下操作,以便作为对比。

首先我发现其实所有有网络通信功能的程序都会去检测HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters\

这个键下面是否存在UseHostsFile值是否存在,数据是多少。但是我发现无论XP还是8.1都没有该值,但是根据之前的实验可知是XP可以正常读取hosts文件的,所以可以断定这个是无关项。(不过根据这个判断,原来Dnscache服务(也就是在服务中显示名称为DNS Client的服务,用于缓存DNS解析的结果)是可以手动强制不读取hosts文件的,修改这个键值即可)

然后我发现一个怪异的现象,每次我手动修改hosts文件后,在8.1下会显示出一个名为svchost.exe的进程试图访问hosts文件但是结果为Acces Denied。在XP下,也有同样名称的进程试图访问hosts文件但是结果却是Success的。

根据消息记录器提供的进程的PID,追踪到其承载的服务中有一个共同的服务就是DNS Client。于是可以断定肯定是上述提到的DNS Client服务出现问题了。因为出现访问文件被拒,肯定是帐户问题,于是我习惯性地打开DNS Client的属性页,转到登录选项卡,发现其使用的帐户不是默认本地系统帐户,而是名为“Network Service”的内置安全主体。

到此一切都明了了,归根到底还是权限问题。DNS Client服务使用的帐户不是system,而是Network Service。虽然我给system帐户赋予了完全的访问控制,但是根据我开篇的截图可以发现,我里面缺少了Network Service的安全主体。而现在我们可以断定system帐户和Network Service安全主体是没有关联的,所以才导致了DNS Client服务启动后无法正常读取hosts文件,而导致hosts文件无效。

解决办法就是:编辑etc文件夹的访问权限,添加Network Service安全主体并赋予至少允许读取的权限,然后重新启动DNS Client服务即可。目前我的hosts已经一切正常。


题外话:在使用消息记录器做实验的时候,发现一点值得提及的:

当没有关闭DNS Client服务时,每次更新hosts文件后,只会有svchost.exe进程去读取hosts文件。但是当关闭DNS Client服务后,所有有网络通信功能的进程都会独立去读取这个hosts文件。

而且,在没有关闭DNS Client服务时,已知仅有svchost.exe进程去读取hosts文件,但也仅仅读取一次hosts,在直至下一次修改hosts文件前,svchosts.exe都没有反复第二次读取hosts文件,无论期间其他的程序创建了多少次网络访问的请求。但是当关闭服务后,所有有网络通信功能的进程每一次访问网络时都会独立去读取hsots文件,不管hosts文件是否有更新。

所以我猜想出hosts的工作原理:

首先我们知道,所有具有网络通信功能的进程都需要包含网络通信模块DLL。其实在这个DLL编写之初,并无考虑到DNS Client服务的存在。所以其实关闭DNS Client服务后的表现是原始的处理过程:每个进程独立管理自己的网络连接,处理自己的网络地址解析(windows网络通信模块的确一开始也是这样制定的)。而自己处理自己的网络地址解析,当然有一个步骤就是首先解析hosts文件了,所以每个有网络通信功能的进程都会独立去访问hosts文件并解析它。而且这时候并无缓存机制,每次读取解析完毕立即释放,待下次网络地址解析请求发生时再一次读取hosts文件,即使期间hosts并没有更新。

而DNS Client服务是后来才出现的,目的是解决DNS解析的混乱吧。不管其出现是为了什么,反正其就把网络地址解析这个功能独揽过去了。这个时候开始,每个有网络访问功能的进程包含的网络通信模块在处理网络地址解析的时候,都会首先去看系统中是否启动了DNS Client服务,如果有启动,那就把请求交由它来完成。所以对于hosts更新的维护,仅仅需要在DNS Client服务中进行就可以了,无需每个进程都去读取hosts文件。所以就有了上面提到的流程:每次更新hsots文件后,仅仅有svchosts.exe进程去读取hosts文件,而其他进程在访问网络的时候,不再产生hosts文件的读取记录。而且,svchost.exe进程并没有每来一个网络地址解析请求就更新一次hosts文件,相反,它等到hosts下一次更新的时候才再次读取,这期间其一直使用自己读入的缓存。

所以可以看到,DNS Client服务的确是有好处的,其统一了对网络地址解析的访问,让网络请求有序化。而我猜统一的访问是为了加入缓存机制铺路的。这是因为,如果是“独立自治”又采取缓存机制的话,那每个进程都要独立监视hosts文件,显然不是明智的做法。加入了缓存机制后,使得对hosts文件的访问大大减少,不用每次访问网络都需要读取一遍hosts文件,而是使用缓存好的数据,这样可以提高系统的处理速度。

Windows 家庭版 | 以前的 Windows 版本 | Internet 和连接

锁定的问题。 此问题已从 Microsoft 支持社区迁移。 你可投票决定它是否有用,但不能添加评论或回复,也不能关注问题。

0 个注释 无注释

问题作者接受的答案

  1. 匿名
    2014-06-10T03:43:48+00:00

    抱歉,现在才回复。

    很高兴你问题解决了,并且对原理进行了分析。

    解决步骤:

    按Windows 徽标键 + X键,点击“命令提示符(管理员)”,依次输入以下命令按回车键(Enter)执行:


    SC stop Dnscache

    SC config Dnscache obj= "NT AUTHORITY\NetworkService"

    TAKEOWN /F "%windir%\System32\drivers\etc" /A

    icacls "%windir%\System32\drivers\etc" /grant "NT AUTHORITY\NetworkService":RX

    SC start Dnscache

    命令解释:

    1. 停止Dnscache(DNS Client)服务
    2. 将运行Dnscache服务的安全主体配置为Network Service
    3. 将etc文件夹所有权交给管理员组
    4. 为Network Service添加在etc文件夹中的读取和执行访问权限
    5. 启动Dnscache服务

    以上命令从社区成员**阿童木奥特曼**提供的解决方法中归纳,解释权归其所有。

    1 个人认为此答案很有帮助。
    0 个注释 无注释

问题作者接受的答案

  1. 匿名
    2014-06-07T18:39:35+00:00

    您好!

    其实我这些天一直在试图找到一个办法,来检测windows是否成功读取到了hosts文件。因为现在的情况,非常像windows本身漠视了hosts文件的存在(但是我的确没有弄错路径)。所以如果能有个办法来检测到windows是否成功读取了hosts文件就好了。

    我在想,windows是否会缓存hosts文件,这样的话,内存中应该有个hosts文件的副本,那可能有某种途径能读取这片内存空间,看看内容是否和实际hosts文件的内容对应即可判断是否成功读取了。

    如果windows不缓存hosts文件,而是直接每次请求一次DNS解释就打开一次hosts文件检测是否有对应映射的话,那应该也可以有个办法检测到windows是否有触动hosts文件,是否触动成功等。比如是否会产生一些消息记录?

    苦于没有找到相应的检测办法,所以不知您是否有一些高见?

    非常感谢这些天来王小石 和 John Wu 的倾力帮助,给了很多很有帮助的提示!

    现在问题已经被我自己解决掉了,公布如下:

    根据引用中我的猜想,我使用了消息记录器来跟踪与hosts文件有关的系统消息。为了对比,我同时在windows 8.1和虚拟机中运行的windows XP下操作,以便作为对比。

    首先我发现其实所有的网络的程序都会去检测HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters\

    这个键下面是否存在UseHostsFile值是否存在,数据是多少。但是我发现无论XP还是8.1都没有该值,但是根据之前的实验可知是XP可以正常读取hosts文件的,所以可以断定这个是无关项。(不过根据这个判断,原来Dnscache服务(也就是在服务中显示名称为DNS Client的服务,用于缓存DNS解析的结果)是可以手动强制不读取hosts文件的,修改这个键值即可)

    然后我发现一个怪异的现象,每次我手动修改hosts文件后,在8.1下会显示出一个名为svchost.exe的进程试图访问hosts文件但是结果为Acces Denied。在XP下,也有同样名称的进程试图访问hosts文件但是结果却是Success的。

    根据消息记录器提供的进程的PID,追踪到其承载的服务中有一个共同的服务就是DNS Client。于是可以断定肯定是上述提到的DNS Client服务出现问题了。因为出现访问文件被拒,肯定是帐户问题,于是我习惯性地打开DNS Client的属性页,转到登录选项卡,发现其使用的帐户不是默认本地系统帐户,而是名为“Network Service”的内置安全主体。

    到此一切都明了了,归根到底还是权限问题。DNS Client服务使用的帐户不是system,而是Network Service。虽然我给system帐户赋予了完全的访问控制,但是根据我开篇的截图可以发现,我里面缺少了Network Service的安全主体。而现在我们可以断定system帐户和Network Service安全主体是没有关联的,所以才导致了DNS Client服务启动后无法正常读取hosts文件,而导致hosts文件无效。

    解决办法就是:编辑etc文件夹的访问权限,添加Network Service安全主体并赋予至少允许读取的权限,然后重新启动DNS Client服务即可。目前我的hosts已经一切正常。


    题外话:在使用消息记录器做实验的时候,发现一点值得提及的:

    当没有关闭DNS Client服务时,每次更新hosts文件后,只会有svchost.exe进程去读取hosts文件。但是当关闭DNS Client服务后,所有有网络通信功能的进程都会去读取这个hosts文件。

    而且,在没有关闭DNS Client服务时,具有网络通信功能的进程访问网络都不会触发hosts文件读取的消息。但是当关闭服务后,所有有网络通信功能的进程每一次访问网络时都会触发对hsots文件读取的消息,而且是其本身单独地去读取和解析的,并无委托一个公共进程去读取和解析hosts文件。

    所以我猜想出hosts的工作原理:

    首先我们知道,所有具有网络通信功能的进程都需要包含网络通信模块DLL。其实在这个DLL编写之初,并无考虑到DNS Client服务的存在。所以其实关闭DNS Client服务后的表现是原始的处理过程:每个进程独立管理自己的网络连接,处理自己的网络地址解析(windows网络通信模块的确一开始也是这样制定的)。而自己处理自己的网络地址解析,当然有一个步骤就是首先解析hosts文件了,所以每个有网络通信功能的进程都会独立去访问hosts文件并解析它。

    而DNS Client服务是后来才出现的,目的是解决DNS解析的混乱吧。不管其出现是为了什么,反正其就把网络地址解析这个功能独揽过去了。这个时候开始,每个有网络访问功能的进程包含的网络通信模块在处理网络地址解析的时候,都会首先去看系统中是否启动了DNS Client服务,如果有启动,那就把请求交由它来完成。所以对于hosts更新的维护,仅仅需要在DNS Client服务中进行就可以了,无需每个进程都去读取hosts文件。所以就有了上面提到的流程:每次更新hsots文件后,仅仅有svchosts.exe进程去读取hosts文件,而其他进程在访问网络的时候,不再产生hosts文件的读取记录。

    所以可以看到,DNS Client服务的确是有好处的,其减少了过多对hosts文件的读取,统一了对网络地址解析的访问。而且不像之前“独立自治”那样,每个进程每次访问网络地址都要读取hosts文件解析一遍,不去缓存hosts文件,而是仅仅读取一次最新的hosts文件,然后就缓存到DNS Client自己的内存空间中,每次解析就像缓存索取数据即可,可以加快访问。

    0 个注释 无注释

23 个其他答案

排序依据: 非常有帮助
  1. 匿名
    2014-06-04T06:38:43+00:00

    您好,

    感谢王小石 的热心答复。

    请问您之前也是这样操作的吗?您是如何更改Host文件的呢?

    您还可以尝试使用其他IP地址取代本地回环地址进行测试确认下结果。

    0 个注释 无注释
  2. 匿名
    2014-06-04T06:17:42+00:00

    您好!非常感谢您的细致回复!

    之前我已经尝试过切换多种编码方式,而且也试过删除再创建hosts文件,但是依然是无效的。

    现在也一一尝试了您的方法,也不见效果,ping  www.baidu.com的时候依然没有往127.0.0.1地址发送数据。

    再次感谢您的回答,不知是否还有其他可能的原因?

    0 个注释 无注释
  3. 匿名
    2014-06-04T01:48:00+00:00

    可能是hosts文件编码错误,尝试:

    按Windows 徽标键 + X键,点击“命令提示符(管理员)”,依次输入以下命令按回车键(Enter)执行:

    chcp 936

    type "%windir%\System32\drivers\etc\hosts"

    查看能否正常显示hosts文件内容而不是乱码

    • 如果是乱码,继续在命令提示符中执行:

    del "%windir%\System32\drivers\etc\hosts"

    echo 127.0.0.1 www.baidu.com >"%windir%\System32\drivers\etc\hosts"

    再次尝试解析www.baidu.com 能否正常

    0 个注释 无注释