在Ubuntu系统上想要通过ipv6来上网,结果发现通过DHCP获取到了ipv6地址却无法连接外网。

ping6 ipv6.google.com

数据包有去无回,100% loss 。

奇怪的是通过DSL PPPoE拨号连接显示两个global的ip:

ifconfig ppp0

  inet6 地址: 2001:250:1006:dff0:4913:2aa5:8075:7c01/64 Scope:Global
  inet6 地址: 2001:250:1006:dff0:99b1:935b:57a5:9b10/64 Scope:Global
  inet6 地址: fe80::99b1:935b:57a5:9b10/10 Scope:Link

通过traceroute6发现数据包从尾号为7c01的那个地址发出的(记为地址A),通过查询学校的计费认证服务器的web页面看到实际分配给我的ip只有那个尾号为9b10的地址(地址B)。

第一次遇到这种情况,很不理解。于是想将地址A直接干掉,把它屏蔽或删掉。于是搜索删除已获取ip的方法,发现ip命令的del参数可以:

ip -6 addr show ppp0  #显示出指定接口的ipv6
ip -6 addr del 地址A dev ppp0 #或者使用 ifconfig 接口 inet6 del v6地址

将地址A删掉后可以成功上ipv6的网站了,可是高兴了没几分钟又上不了了,地址又回来了。

注意到ip show显示的地址A是scope global temporary dynamic的,居然是个临时地址。

继续搜索什么是临时地址以及为什么要使用临时地址。。。

大概意思是不想固定一个设备的ip,防止被追踪定位,为了隐私考虑。因为使用ipv6地址无需像ipv4一样使用NAT公用一个ip,设备间连接更容易,但容易造成隐私泄漏。为此操作系统可以选用多个临时ip,每个ip有固定的生命周期。ipv6自动配置时使用你的MAC地址来选择一个ip地址,这样其它设备根据你的ip地址可能会算出你的mac地址(全球唯一)。

这确实是不错的做法,现在的疑问就是这些临时ip的生成和使用机制是什么以及我现在为什么不能用它来上网?

只了解到临时地址的作用是在用户对外发起连接的时候充当连接发起的IPv6地址,这一行为的目的在于保证主机在对外通信 时候的匿名性。这个地址是由路由前缀和由主机随机生成的接口标识组成的。这个地址是有有效期限制的,几个小时或者几天,在期间,系统一直以这个地址为主机 地址向外发出连接和请求。每一个时刻只有一个临时地址是有效的,在一个地址过期时会立刻生成一个新的地址作为新的临时地址。已经过期的地址不会立即被删除,它会保存几个小时或者几天,此时过期的临时地址不能对外发起连接,但是可以接受外部发来的之前请求的信息。下面网站上指出在 RFC 3041 中描述了一种备用的 IPv6 接口标识,它是随机生成的,并且随时间变化而变化。

https://msdn.microsoft.com/zh-cn/library/cc736439(v=ws.10).aspx

至于为什么在我电脑上使用临时地址无法连接还不得知,,,

当务之急是把临时ip给取消掉,本来获取到的ip就是动态的,也无需这么注重隐私,况且现在大多数服务器都是用静态ip啊。

原来ubuntu的多个版本都是如下(linux内核参数,可使用cat、echo来查看修改/proc/sys):

 

sudo sysctl -a | grep tempaddr
    net.ipv6.conf.all.use_tempaddr = 2
    net.ipv6.conf.default.use_tempaddr = 2
    net.ipv6.conf.eth0.use_tempaddr = 2
    net.ipv6.conf.lo.use_tempaddr = 2

值为2表示系统打开了该选项并且在建立连接时优先使用临时地址。

只需改为0并重启即可(重启网络),
执行sudo sysctl net.ipv6.conf.ppp0.use_tempaddr=0 可以临时改变ppp0接口的use_tempaddr的值。
然而在执行下列命令时又被重置为2。
  sudo /etc/init.d/networking restart #手动配置的网络
  sudo pkill NetworkManager ; sudo NetworkManager #NetworkManager托管的 )
一劳永逸的方式为
尝试将net.ipv6.conf.all.use_tempaddr=0写入/etc/sysctl.conf
sysctl -p  #读取sysctl.conf使新设置生效,但并不加载sysctl.d目录中的文件
sysctl --system #加载所有的配置文件,像/etc/sysctl.d/*等
重启之后发现不再产生临时地址了,过了几个月,在我升级内核之后发现上述做法不可行了。
发现/etc/sysctl.d这个目录下有个10-ipv6-privacy.conf 内容如下:
# IPv6 Privacy Extensions (RFC 4941)
# ---
# IPv6 typically uses a device's MAC address when choosing an IPv6 address
# to use in autoconfiguration. Privacy extensions allow using a randomly
# generated IPv6 address, which increases privacy.
#
# Acceptable values:
# 0 - don’t use privacy extensions.
# 1 - generate privacy addresses
# 2 - prefer privacy addresses and use them over the normal addresses.
net.ipv6.conf.all.use_tempaddr = 2
net.ipv6.conf.default.use_tempaddr = 2
将net.ipv6.conf.default.use_tempaddr改为0后
执行sysctl --system重新拨号连接,就不再有临时地址了。

不清楚all与default的区别,似乎是all的设置会被特定接口的设置覆盖,default的值在内核启动时设置。

http://tldp.org/HOWTO/Linux+IPv6-HOWTO/proc-sys-net-ipv6..html 上面写着:

conf/default/*

Change the interface-specific default settings.

conf/all/*

Change all the interface-specific settings.

Exception: conf/all/forwarding

(设置ipv6转发的all.forwarding参数有点特殊,如果设为0则全局禁止了数据包转发,你不能为每个设备接口设置不同的转发开关。这跟ipv4不同。)

2. pppoeconf 拨号+ipv6设置
使用命令行工具pppoeconf管理网络

用户名(username)与密码(password)存储在/etc/ppp/chap-secrets文件中。
生成的配置文件会存放于/etc/ppp/peers目录下, 并且会改动/etc/network/interfaces;

查看手册$man pppd 可以看到有这么一行:

+ipv6 Enable the IPv6CP and IPv6 protocols.

若打算启用IPv6,需要添加+ipv6/etc/ppp/peers/<file name>

如果开启了IPv6内核转发,会获取不到IPv6地址,这与Router Advertisements这个术语有关,相关配置是accept_ra

编辑 /etc/sysctl.conf

net.ipv6.conf.default.accept_ra=2
net.ipv6.conf.all.accept_ra=2
net.ipv6.conf.default.use_tempaddr=0
net.ipv6.conf.all.use_tempaddr=0