An IPv6 Enabled NTP Client for Windows in Python

Python NTP library (ntplib) offers a simple interface to query NTP servers from Python. But it does not support IPv6 NTP servers. I wrote a patch for ntplib to support IPv6 connections. You can download the patch file here and the patched library here.

The code bellow is a simple IPv6 enabled NTP client (ntpdate.py) in Python for Windows, using the patched ntplib. It doesn't (and won't) support Linux because the official NTP release offers IPv6 support on that platform.

#!/usr/bin/env python
# ntpdate.py - set the date and time via NTP
# An IPv6 enabled ntp client, for Windows ONLY.

import ntplib, time
from os import system
from sys import argv

def usage():
  print '''Usage: ntpdate.py  [-qh] server
Example:
  ntpdate.py 210.72.145.44      # IPv4
  ntpdate.py ntp6.remco.org     # IPv6
Options:

  -q     Query only - don't set the clock.
  -h     Print this message.

IPv6 NTP Server List:
  ntp6.remco.org               [2001:888:1031::2]
  ntp6.space.net               [2001:608:0:dff::2]
  time.buptnet.edu.cn          [2001:da8:202:10::60]
  time.join.uni-muenster.de    [2001:638:500:717:2e0:4bff:fe04:bc5f]
  ntp.sixxs.net                [2001:1291:2::b]
  ntp.eu.sixxs.net             [2001:808::66]
  ntp.us.sixxs.net             [2001:1291:2::b]
  ntp.rhrk.uni-kl.de           [2001:638:208:9::116]
  ntp.ipv6.uni-leipzig.de      [2001:638:902:1::10]
  ntp.hexago.com               [2001:5c0:0:2::25]
  ntp1.bit.nl                  [2001:7b8:3:2c::123]

Report bugs to http://solrex.org.'''
  sys.exit()

def main():
  ntp_svr = ''
  query = False

  for a in argv[1:]:
    if a == '-q':
      query = True
    elif a == '-h':
      usage()
    else:
      ntp_svr = a
  if ntp_svr == '':
    usage()

  c = ntplib.NTPClient()
  res = c.request(ntp_svr, version=3)
  t_epoch = res.offset + res.delay + time.time()
  t = time.localtime(t_epoch)
  centi_sec = t_epoch%1 * 100
  time_str = time.strftime('%H:%M:%S', t)
  if not query:
    system('time %s.%2.0f' % (time_str, centi_sec))
    date_str = time.strftime('%Y-%m-%d', t)
    system('date %s' % date_str)
  if query:
    print 'server %s, stratum %d, offset %f, delay %f' % (
           ntp_svr, res.stratum, res.offset, res.delay)
  print '%s %s ntpdate.py: time server %s offset %f sec' % (
         time.strftime('%d %b', t), time_str, ntp_svr, res.offset)

if __name__ == '__main__':
  main()

IPV6 获取地址却无法使用的解决方案

最近我的 WinXP 经常无法连接 IPV6 站点,但是 IPV6 地址的获取是正常的,同一台电脑上的 Ubuntu IPV6 工作也正常。经过一些摸索发现可能是以下两个原因造成的:

1. 分配到 2002 开头的 IPV6 地址并使用了它。2002::/16 格式的地址是 6to4 的地址,不是 native 的 IPV6 地址,所以在 IPV4+V6 双栈网络中不应该使用 2002::/16 格式的地址。执行 ping6 ipv6.google.com 可以看到自己使用的是什么 IPV6 地址。

之所以会产生 2002::/16 格式的地址,一个很可能的原因是网络中的 Windows Vista 操作系统默认会发送 IPV6 的路由器公告。使用

netsh interface ipv6 show interface "本地连接"

命令可以查看本地连接的参数,其中有一条:“发送路由器公告”,一定要设置为“否”。如果您的这个选项是“是”,那么您可以使用这个命令关闭它:

netsh interface ipv6 set interface “本地连接” advertise=disabled

如果获得的全部是 2002 开头的地址,可以使用下面命令进行重分配:

netsh interface ipv6 reset

2. IPV6 的路由表(网关)不对。tracert6 ipv6.google.com 就能看到本机是经过什么路由到 ipv6.google.com 的。如果从第一跳就显示连接超时,应该就是路由表出了问题。

两个问题的解决方案如下:

netsh interface ipv6 set prefixpolicy 2001::/16 1 1 persistent

上面这条命令的意思是设置 Windows 更偏好使用 2001 开头的 IPV6 地址,避免使用 2002 开头的地址。如果您 ping ipv6.google.com 使用的是 2001 开头的地址,那么您不必执行上面这条命令。

netsh interface ipv6 add route 2001::/16 "本地连接" fe80::21a:30ff:fe4f:7000 persistent

上面这条命令的意思是为 2001 开头的 IPV6 地址使用正确的网关 fe80::21a:30ff:fe4f:7000(中科院某公寓)。这个网关可能随着用户所在网络的不同而不同,简单点儿的方法可以去看正常用户的 ifconfig 网关地址。

之后执行 ping6 ipv6.google.com 看能否 ping 通,如果能 ping 通就说明 IPV6 工作正常了。

如果您经过以上两步之后仍然无法解决问题的话,您可以使用 netsh interface ipv6 reset 命令来重置所有修改。

PS:

1. 如何确定网络中哪些主机在发送路由器公告?

2002 后面的两个字段就是该主机的 IPV4 地址,比如 2002:3b41:177e:8:18fc:7649:9e1d:2880,其中 3b41:177e 从 16 进制显示换算成 IPV4 的 10 进制显示地址就是 59.65.23.126。一般来说,V4 地址的分配更有规律,您可以从 V4 地址大致确定该主机的位置。

2. 如何确定虚假的路由记录?

一般来说,IPV6 地址的最后 4 个域应该从网卡的物理地址中获得,假设网卡物理地址是:00-17-31-94-99-EA,在 3,4 字节之间插入 FFFE 换成 EUI-64 格式是:00-17-31-FF-FE-94-99-EA,再对第一个字节的第二位取反,就变成 02-17-31-FF-FE-94-99-EA,然后装载到 IPV6 的本地地址中,就变成本地地址 fe80::217:31ff:fe94:99ea。根据网段的不同,在前面加上 4 个网络域,就是主机的公网地址 2001:xxxx:xxxx:xxxx:217:31ff:fe94:99ea。

由于双栈路由器是使用同一个网卡提供 V4 和 V6 的路由,那么路由器的 V4 地址和 V6 地址的物理地址是一样的。通过 ping gateway_ipaddress_v4,然后 arp -a 看 V4 的网关地址对应的物理地址,与上面 V6 网关本地地址中获得的物理地址相对照,就可以确定某路由记录是否为可用的记录。

天下没有免费的午餐

前两天才说过希望免费的 IPv6 服务能一直继续下去,谁知道今天就发现了原来 IPv6 免费电话不是无限制使用的,大概是给了能打多长时间固定电话的优惠,然后就不能打了,不知道这个限制是按月给的还是像 Skype 一样只是一个初始优惠。

不过还好的是 IPv6 免费电视还是能继续看下去的...

汇报一下近况吧,从南京回来之后就恢复了以前的生活,课程只剩下一节,周末依然去公司兼职。公司才建立了一个内部知识库,前两天都在添加一些和调试有关的词条,以便于一个新来的同事能更快的了解调试相关的知识,这也是为什么前面一篇文章是关于 TWiki 语法的介绍。其实在学校时候也在自己电脑上安装过 TWiki,是在 Linux 上装的,但是装好之后那个侧栏一直是拉在主页面的下面,很诡异的问题,就没有用。

在学校时就是为考试复习复习,有空看看电影,再写点别的东西。我准备把那个 hacking《自己动手写操作系统》系列继续写下去,但由于博客页面限制,所以打算将此系列排版成一本 pdf 电子书。LaTeX 的模板已经编辑好了,现在正在为前面已经发布的内容增加图片和更详细的介绍,不知道能不能在回家之前发布第一个 revision,尽力吧。

南京移动推出了定向漫游服务,在定向漫游城市接打电话只需要 5 毛,这就更动摇了我换号的决心。我决定把北京的动感地带卡号卖掉,北京移动太差劲了:资费贵、网站服务不完善、不能异地充值、服务种类少。再说我现在用手机打电话最多的就是给女朋友,北京号到南京了也不好用,干嘛换号啊?所以朋友们注意了:我现在仍然使用的是我三年前开通的南京移动手机号,不要删除哈。

yo2 开通了邮件发文服务,这下我就可以只发一次邮件同时更新我的三个博客了,不错不错!但是我的主博客还是这里哈,欢迎多来逛逛!

Cool IPv6

中科院通了 IPv6 试验网,现在我们可以用 IPv6 网络看免费的高速网络电视,将近四十个台。还可以用 IPv6 打免费电话,固定电话有点儿杂音,效果还不错,手机貌似不好打。最重要的是,连流量费都不算,哈哈!!!

希望免费的午餐持续时间越长越好!*_*