wan口的拨号有好几种方式,SLAAC, stateless DHCPv6, stateful DHCPv6, DHCPv6-PD,这些请求方式在odhcpv6里面都可以配置。
开启openwrt .config配置
CONFIG_PACKAGE_odhcp6c=y
CONFIG_PACKAGE_odhcp6c_ext_prefix_class=0
CONFIG_PACKAGE_odhcp6c_ext_cer_id=0
odhcp6c的启动需要在/etc/config/network uci里面配置允许,类似IPV4的udhcpc
config globals 'globals'
option ula_prefix 'auto'
config interface 'lan'
option def_ifname 'eth0'
option ifname 'eth0'
option force_link '1'
option type 'bridge'
option proto 'static'
option igmp_snooping '0'
option ipaddr '192.168.18.1'
option def_ipaddr '192.168.18.1'
option res_ipaddr '10.1.2.1'
option netmask '255.255.255.0'
option ip6assign '60'
option macaddr 'DC:4B:DD:1D:FA:48'
config interface 'wan'
option ipv6 '1'
option def_ifname 'eth1'
option ifname 'eth1'
option proto 'dhcp'
option web_proto 'dhcp'
option macaddr 'DC:4B:DD:1d:fa:49'
config interface 'wan6'
option ifname 'eth1'
option proto 'dhcpv6'
配置好之后需要重启/etc/init.d/network restart
里面会执行ubus call network reload
然后就是一系列的ubus传输,最终会调用到/lib/netifd/proto
里面对应的脚本,脚本netifd-proto.sh
脚本里面会调用_proto_do_setup
函数,启动各个协议进程。
/lib/netifd/proto$ ls
dhcp.sh
ipv4的启动在./lib/netifd/proto/dhcp.sh
脚本里面的proto_dhcp_setup
函数
proto_export "INTERFACE=$config"
proto_run_command "$config" udhcpc -R \
-p /var/run/udhcpc-$iface.pid \
-s /lib/netifd/dhcp.script \
-f -t 0 -i "$iface" \
${ipaddr:+-r $ipaddr} \
${hostname:+-H $hostname} \
${vendorid:+-V $vendorid} \
$clientid $broadcast $dhcpopts
ipv6的启动在./lib/netifd/proto/dhcpv6.sh
脚本里面的proto_dhcpv6_setup
函数
proto_export "INTERFACE=$config"
proto_run_command "$config" odhcp6c \
-s /lib/netifd/dhcpv6.script \
$opts $iface
udhcpc -R -p /var/run/udhcpc-eth1.pid -s /lib/netifd/dhcp.script -f -t 0 -i eth1 -C
odhcp6c -s /lib/netifd/dhcpv6.script -P0 -t120 eth1
odhcp6c启动之后,在netstat下面可以看到udp的546端口,因为DHCPv6的客户端使用546端口,服务器使用的是547端口
root@zihome:/# netstat -naup | grep dhcp
netstat: showing only processes with your user ID
udp 0 0 :::546 :::* 1481/odhcp6c
udp 0 0 :::547 :::* 1347/odhcpd
上面提到了wan口的拨号是有很多种的,而且wan口的ifname也是会变化的。
wan口拨号的uci配置在官网可以查看到
https://openwrt.org/docs/guide-user/network/ipv6/start
Name | Type | Required | Default | Description |
---|---|---|---|---|
reqaddress | [try,force,none] | no | try | Behaviour for requesting addresses |
reqprefix | [auto,no,0-64] | no | auto | Behaviour for requesting prefixes (numbers denote hinted prefix length). Use ‘no’ if you only want a single IPv6 address for the AP itself without a subnet for routing |
config globals 'globals'
option ula_prefix 'auto'
config interface 'lan'
option proto 'static'
option ip6assign '60'
config interface 'wan6'
option ifname 'eth1'
option proto 'dhcpv6'
所以默认情况,udhcp6c的dhcpv6使用SLAAC + stateful DHCPv6 + DHCPv6-PD
的方式进行拨号的。
所以路由器wan口获取到多少个ipv6地址,就看上一级的服务器能提供多少种服务。
如果上级只有dhcpv6服务器,则wan只获取到一个Global 地址,加上自己本地的Link地址,是两个ipv6地址
root@zihome:/# ifconfig eth1
eth1 Link encap:Ethernet HWaddr 08:10:7B:A7:26:3C
inet6 addr: fe80::a10:7bff:fea7:263c/64 Scope:Link
inet6 addr: 2001:db8:0:1::254/128 Scope:Global
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1510 errors:0 dropped:0 overruns:0 frame:0
TX packets:3731 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:252070 (246.1 KiB) TX bytes:501125 (489.3 KiB)
如果上级既有dhcpv6服务器,也有ra服务器,则就会有三个地址,一个本地Link,一个dhcp服务器分配的Global地址,一个ra服务器下发前缀算出来的Global地址。
eth1 Link encap:Ethernet HWaddr 08:10:7B:A7:26:3C
inet6 addr: 2016:ac11:5cad:0:a10:7bff:fea7:263c/64 Scope:Global
inet6 addr: fe80::a10:7bff:fea7:263c/64 Scope:Link
inet6 addr: 2001:db8:0:1::254/128 Scope:Global
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2288 errors:0 dropped:0 overruns:0 frame:0
TX packets:5709 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:387179 (378.1 KiB) TX bytes:830273 (810.8 KiB)
支持DHCP-PD功能,所以在发送DHCP Solicit
消息里面如果带了IA-Prefix的请求,则服务器就会在IA Prefix字段里面附带自己要在br-lan端口设置的ipv6端口地址前缀,2001:db8:0:f00::1/60
,用于下发地址给lan口的设备的地址前缀,然后设置到br-lan的ifconfig里面。
在odhcp6c客户端发送DHCP-PD之后,会在br-lan口设置dhcp服务器的IP前缀,如下2001:db8:0:f00::,这样lan端就可以使用这个前缀地址通过odhcpd服务器下发给下一级ipv6地址了。
root@zihome:/# ifconfig br-lan
br-lan Link encap:Ethernet HWaddr 08:10:7B:A7:26:3B
inet addr:192.168.18.1 Bcast:192.168.18.255 Mask:255.255.255.0
inet6 addr: 2001:db8:0:f00::1/60 Scope:Global
inet6 addr: fe80::a10:7bff:fea7:263b/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:391 errors:0 dropped:0 overruns:0 frame:0
TX packets:248 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:32339 (31.5 KiB) TX bytes:74394 (72.6 KiB)
ohdcp6c的静态IP方式将uci的值单独抽出来,没有跟上面的在一起,主要有如下参数
Name | Type | Required | Default | Description |
---|---|---|---|---|
ip6addr | ipv6 address | yes, if no ipaddr is set | (none) | |
ip6ifaceid | ipv6 suffix | no | ::1 | |
ip6gw | ipv6 address | no | (none) | Assign given IPv6 default gateway to this interface |
ip6assign | prefix length | no | (none) | Delegate a prefix of given length to this interface (see Downstream configuration below) |
ip6hint | prefix hint (hex) | no | (none) | Hint the subprefix-ID that should be delegated as hexadecimal number (see Downstream configuration below) |
ip6prefix | ipv6 prefix | no | (none) | IPv6 prefix routed here for use on other interfaces (Barrier Breaker and later only) |
ip6class | list of strings | no | (none) | Define the IPv6 prefix-classes this interface will accept |
dns | list of ip addresses | no | (none) | DNS server(s) |
dns_search | list of domain names | no | (none) | Search list for host-name lookup |
metric | integer | no | 0 | Specifies the default route metric to use |
# cat /etc/config/network
config interface wan
option ifname eth1
option proto static
option ip6addr 2001:db80::2/64 # Own address
option ip6gw 2001:db80::1 # Gateway address
option ip6prefix 2001:db80:1::/48 # Prefix addresses for distribution to downstream interfaces
option dns 2001:db80::1 # DNS server
config interface lan
option proto static
option ip6assign 60
上面这种方式就把wan接口配置成静态ipv6了模式了,这样ipv4也得是静态模式,所以一般在wan6里面设置成static,而wan里面ipv4的还是正常的dhcp/static
# cat /etc/config/network
config interface 'wan'
option ipv6 '1'
option def_ifname 'eth1'
option ifname 'eth1'
option proto 'dhcp'
option web_proto 'dhcp'
option macaddr 'DC:4B:DD:1d:fa:49'
config interface 'wan6'
option ifname eth1
option proto static
option ip6addr 2001:db80::2/64 # Own address
option ip6gw 2001:db80::1 # Gateway address
option ip6prefix 2001:db80:1::/48 # Prefix addresses for distribution to downstream interfaces
option dns 2001:db80::1 # DNS server
config interface lan
option proto static
option ip6assign 60
在获取到ipv6地址后,除了使用ifconfig看下信息外,还可以使用ifstatus查看
root@zihome:/tmp/state# ifstatus wan6
{
"up": true,
"pending": false,
"available": true,
"autostart": true,
"uptime": 3195,
"l3_device": "apcli0",
"proto": "dhcpv6",
"device": "apcli0",
"metric": 0,
"delegation": true,
"ipv4-address": [
],
"ipv6-address": [
{
"address": "240e:ff:b112:7b52:dc4b:ddff:fe1d:fa08",
"mask": 64
}
],
"ipv6-prefix": [
],
"ipv6-prefix-assignment": [
],
"route": [
{
"target": "240e:ff:b112:7b52::",
"mask": 64,
"nexthop": "::",
"metric": 256,
"source": "::\/0"
},
{
"target": "::",
"mask": 0,
"nexthop": "fe80::1c6e:5292:2b90:603",
"metric": 1024,
"valid": 8961,
"source": "240e:ff:b112:7b52:dc4b:ddff:fe1d:fa08\/64"
},
{
"target": "::",
"mask": 0,
"nexthop": "fe80::1c6e:5292:2b90:603",
"metric": 1024,
"valid": 8961,
"source": "::\/128"
}
],
"dns-server": [
"fe80::1c6e:5292:2b90:603"
],
"dns-search": [
],
"inactive": {
"ipv4-address": [
],
"ipv6-address": [
],
"route": [
],
"dns-server": [
],
"dns-search": [
]
},
"data": {
"passthru": "00170010fe800000000000001c6e52922b900603"
}
}
现在的手机热点,一般都可以提供ipv6地址,中继成功后获取到如下ipv6地址,跟手机在同一个网段
手机可以在http://www.test-ipv6.com/上面看到自己的网段
然后路由器设置成无线中继模式,连接手机的热点,wan6的ifname设置成apcli0,dhcpv6模式
config interface 'wan6'
option ifname 'apcli0'
option proto 'dhcpv6'
连接成功后,可以看到以下信息,一个本地链路地址和一个全球单播地址。
root@zihome:/tmp/state# ifconfig apcli0
apcli0 Link encap:Ethernet HWaddr DE:4B:DD:1D:FA:08
inet addr:172.20.10.13 Bcast:172.20.10.15 Mask:255.255.255.240
inet6 addr: 240e:ff:b112:7b52:dc4b:ddff:fe1d:fa08/64 Scope:Global
inet6 addr: fe80::dc4b:ddff:fe1d:fa08/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:33129 errors:0 dropped:0 overruns:0 frame:0
TX packets:36694 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:16662784 (15.8 MiB) TX bytes:4734313 (4.5 MiB)
使用手机热点获取到的Global ipv6地址是通过EUI64自己算出来的,所以这个地址应该不是dhcpv6服务器下发的,而是通过RA无状态模式生成的。
另外可以看到路由器的br-lan端口是没有全球单播地址的,路由器发出的IA-PD手机没办法回复,没有提供给下一级设备使用的地址。
这时候可以在lan口设置一个同网段的ipv6地址,这样lan端的设备就可以获取到ipv6地址,不过担心会冲突吧,比较不是正在的dhcpv6/ra服务器下发的
root@zihome:/# ifconfig apcli0
apcli0 Link encap:Ethernet HWaddr DE:4B:DD:1D:FA:08
inet addr:172.20.10.13 Bcast:172.20.10.15 Mask:255.255.255.240
inet6 addr: 240e:ff:b4d5:621d:dc4b:ddff:fe1d:fa08/64 Scope:Global
inet6 addr: fe80::dc4b:ddff:fe1d:fa08/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:10193 errors:0 dropped:0 overruns:0 frame:0
TX packets:10338 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:9429739 (8.9 MiB) TX bytes:3842656 (3.6 MiB)
root@zihome:/# ifconfig br-lan add 240e:ff:b4d5:621d:dc4b:ddff:fe1d:fa08/64
root@zihome:/# ifconfig br-lan
br-lan Link encap:Ethernet HWaddr DC:4B:DD:1D:FA:48
inet addr:192.168.18.1 Bcast:192.168.18.255 Mask:255.255.255.0
inet6 addr: 240e:ff:b4d5:621d:dc4b:ddff:fe1d:fa08/64 Scope:Global
inet6 addr: fe80::de4b:ddff:fe1d:fa48/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2742 errors:0 dropped:0 overruns:0 frame:0
TX packets:1626 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:526741 (514.3 KiB) TX bytes:441983 (431.6 KiB)
root@zihome:/#ifconfig br-lan add 240e:ff:b112:7b52::2012/64