缘起
最近开始听很多朋友说 IPv6 已经逐渐普及了,经过这十几二十年的发展。于是我也蠢蠢欲动,尝试在自己的老笔记本上运行一个 IPv6 服务。
首先介绍一下我家的网络情况:联通宽带的光猫,因为信号太差,连了一个 TP-Link 的路由器。宽带是提供了 IPv6 的,在路由器配置里选择开启 IPv6。笔记本是 Macbook-pro,手持一台 iphone,两者连接同一个 WiFi。
我在 iphone 上安装了一个叫 Net Analyzer 的应用,免费的,可以看 IP 地址信息,发起 ping 请求,挺好用的。从这个应用里我看到手机从 WiFi 获取到的 IP 地址(以下皆指v6地址)是 2048 开头。
在笔记本上,通过 ifconfig
命令可以查到我在 en0 下有一个同样以 2048 开头的 IP 地址:
inet6 2408:..:..:..:..:..:..:.. prefixlen 64 autoconf secured // 安全起见,省略掉具体地址
推测出这两个地址应该是同属与一个路由。prefixlen 64
表示 IP 地址的前 64bits 是路由给的前缀,autoconf
表示这个地址是自动配置的, secured
表示这个地址是通过密码学手段生成的(可能是采用 CGA,但我暂时找不到更多信息)。
IPv6 HTTP Server
接下来我决定用 python 在笔记本上建立一个简单的 HTTP 服务:
import socket
from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
class MyHandler(SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/ip':
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write('Your IP address is %s' % self.client_address[0])
return
else:
return SimpleHTTPRequestHandler.do_GET(self)
class HTTPServerV6(HTTPServer):
address_family = socket.AF_INET6
def main():
server = HTTPServerV6(('::', 8080), MyHandler)
server.serve_forever()
if __name__ == '__main__':
main()
代码来自 https://gist.github.com/akoro... 。
将代码保存到一个文件,执行 python [文件名]
,即可在 8080 端口启动简易的Http服务器。
接下来在手机上访问我们笔记本的 IP 地址,从浏览器访问时需要对格式做一些修改:
http://[2048:..:..:..:..:..:..:..]:8080
访问成功!
CGA
尽管我从网上找到了一些资料,证明 Apple 实现了 CGA(cryptographically generated addresses) 地址的生成,但是我找不到如何获取对应的私钥,所以没办法做其它的事情。
All Apple operating systems support IPv6, implementing several mechanisms to protect the privacy of users and the stability of the networking stack. When Stateless Address Autoconfiguration (SLAAC) is used, the IPv6 addresses of all interfaces are generated in a way that helps prevent tracking devices across networks and at the same time allows for a good user experience by ensuring address stability when no network changes take place. The address generation algorithm is based on cryptographically generated addresses as of RFC 3972, enhanced by an interface-specific modifier to warrant that even different interfaces on the same network eventually have different addresses.
我试着将 IP 地址配置从自动模式改为手动,可以正常使用。但 ifconfig 里的 secured
标签也就随之消失了。
ndp
使用 ndp -w
命令可以看到当前使用的 GCA parameters:
% ndp -w
Public Key:
30:81:89:02:81:81:00:ce:a1:d9:a8:9b:80:96:9b:d0:cc:2e:d3:d5:0f:58:01:99:ea:32:46:19:7b:2e:31:ee
e0:60:65:fa:56:0a:5a:02:4f:ec:b8:c5:3a:f6:07:77:6c:17:91:fa:16:a9:06:d8:12:8e:c8:3c:31:32:ad:67
51:fb:b9:2c:86:43:7d:d6:8d:97:da:ff:71:fd:b3:c5:11:5a:5c:91:04:93:86:dc:12:61:3f:23:0a:a2:76:10
85:ff:d7:18:1a:27:53:e7:87:5d:d8:14:11:dd:03:c5:dc:d9:b9:8b:c1:5b:08:cc:73:4e:78:85:74:ee:89:cb
bd:16:03:f0:d5:d6:4f:02:03:01:00:01
Modifier:
d4:d6:d7:57:e2:93:9e:f0:c5:9b:09:8f:b4:59:fd:e8
Security Level: 0
sysctl
最新进展是查到了 sysctl net.inet6.send.cga_parameters
可以配置 CGA 的私钥和公钥。但具体的格式还不清楚。
dhcpclient
皇天不负有心人,在搜索了无数 apple 开源代码之后,我终于找到了 CGA key保存的位置:
% sudo cat /var/db/dhcpclient/CGAKeys.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PrivateKey</key>
<data>
...
</data>
<key>PublicKey</key>
<data>
MIGJAoGBAM6h2aibgJab0Mwu09UPWAGZ6jJGGXsuMe7gYGX6VgpaAk/suMU69gd3bBeR
+hapBtgSjsg8MTKtZ1H7uSyGQ33WjZfa/3H9s8URWlyRBJOG3BJhPyMKonYQhf/XGBon
U+eHXdgUEd0DxdzZuYvBWwjMc054hXTuicu9FgPw1dZPAgMBAAE=
</data>
</dict>
</plist>
直接修改这里应该就可以配置 CGA key 了,哈哈哈,先容我休息一会儿。
IPv6 协议类型
IPv6 包含一系列的协议,为了更好地了解它们,我安装了 WireShark,一个久负盛名的抓包工具。
另外在这个宝藏网址: https://www.iana.org/assignme... 可以看到全部 ipv6 多播地址段的含义。
打开 WireShark,立刻明白了无线网络环境是多么不安全,各种信息一览无余。 在无线网络下捕捉到了以下协议:
Multicast DNS
发送方:我的电脑;接收方: ff02::fb(mDNSv6) 。这是一个多播消息,局域网中的其它节点都可以收到。消息的内容是查询一些本地服务的 IP 地址,例如 AirDrop、打印机、Airplay 等等。
DHCPv6(Dynamic Host Configuration Protocol version 6)
用于主机和路由器之间更新各种配置信息。这是有状态的。
ICMPv6 (Internet Control Message Protocol for IPv6)
ICMPv6 是一种定义了命令格式的协议,很多更高级的协议是基于它。例如 NDP(Neighbor Discovery Protocol) ,NDP包含以下功能:
- Neighbor Discovery (ND) 邻居发现
- Router Discovery (RD) 路由发现
- Address Autoconfiguration 地址自动配置
- Address Resolution 地址解析
- Neighbor Unreachability Detection (NUD)
- Duplicate Address Detection (DAD)
- Redirection
这些功能使用以下几种消息实现:
- Router Solicitation (RS)
- Router Advertisement (RA)
- Neighbor Solicitation (NS)
- Neighbor Advertisement (NA)
- Redirect
NDP 可以支持这些选项能够在 IANA 找到.
我们想要看到的是 SEND(SEcure Neighbor Discovery),一种采用 CGA 对 NDP 进行的扩展,结果发现 MacOS 并没有支持。
自己实现 SEND 协议
没有 SEND 协议,意味着我们想要将 pubkey 绑定到 IP 地址,从而实现在网络层的认证和加密协议的愿望落空了。但没关系,我决定自己实现一个。
我们希望最终实现:在同一无线网络下,比如商场公共 WiFi,Alice 和 Bob 可以通过已知的对方的 pubkey,来实现免配置的安全连接。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。