IPv6 使用差异说明(vs IPv4)

约束限制

  • chrony 支持全局地址(global address),不支持链路本地地址(link-local address)。
  • Firefox 支持通过http/https协议访问全局地址(global address),不支持链路本地地址(link-local address)。

配置说明

设置接口设备 MTU 值

概述

IPv6 场景中会发现整个路由路径中的最小 mtu 的值作为当前链接的 PMTU 的值,源端根据 PMTU 的值确定是否进行分片发送,而在整个路径中的其它设备将不再需要进行分片处理,从而可以降低中间路由设备的负载大小。其中 IPv6 PMTU 设置的最小值为1280。

设置接口设备的 mtu

如果在配置了 IPv6 地址的接口上设置 mtu 的值小于1280(IPv6 PMTU 设置的最小值),则会导致该接口的 IPv6 地址被删除。并且无法再次添加 IPv6 地址。所以在 IPv6 场景中,对接口设备的 mtu 的配置一定要大于等于 1280。具体现象如下:

# ip addr show enp3s0
3: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:62:xx:xx brd ff:ff:ff:ff:xx:xx
    inet 10.41.125.236/16 brd 10.41.255.255 scope global noprefixroute dynamic enp3s0
       valid_lft 38663sec preferred_lft 38663sec
    inet6 2001:222::2/64 scope global
       valid_lft forever preferred_lft forever
# ip link set dev enp3s0 mtu 1200
# ip addr show enp3s0
3: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1200 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:62:xx:xx brd ff:ff:ff:ff:xx:xx
    inet 10.41.125.236/16 brd 10.41.255.255 scope global noprefixroute dynamic enp3s0
       valid_lft 38642sec preferred_lft 38642sec
# ip addr add 2001:222::2/64 dev enp3s0
RTNETLINK answers: No buffer space available
# ip link set dev enp3s0 mtu 1500
# ip addr show enp3s0
3: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:62:xx:xx brd ff:ff:ff:ff:xx:xx
    inet 10.41.125.236/16 brd 10.41.255.255 scope global noprefixroute dynamic enp3s0
       valid_lft 38538sec preferred_lft 38538sec
# ip addr add 2001:222::2/64 dev enp3s0
# ip addr show enp3s0
3: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:62:xx:xx brd ff:ff:ff:ff:xx:xx
    inet 10.41.125.236/16 brd 10.41.255.255 scope global noprefixroute dynamic enp3s0
       valid_lft 38531sec preferred_lft 38531sec
    inet6 2001:222::2/64 scope global
       valid_lft forever preferred_lft forever

有状态自动配置 IPv6 地址

概述

IPv6 与 IPv4 都可以通过 DHCP 的方式获得 IP 地址。IPv6 地址有两种配置方式:无状态自动配置和有状态自动配置。

  • 无状态自动配置

    不需要 DHCP 服务进行管理,设备根据网络 RA(路由公告)获得网络前缀,或者 link-local 地址为固定 fe80::。而接口 ID 则根据 ifcfg 配置 IPV6_ADDR_GEN_MODE 的具体设置来进行自动获得:

    1. IPv6_ADDR_GEN_MODE=“stable-privacy” 则根据设备及网络环境来确定一个随机接口 ID。
    2. IPv6_ADDR_GEN_MODE=“EUI64” 则根据设备MAC地址来确定接口 ID。
  • 有状态自动配置:需要 DHCP 服务器进行管理分配,服从 DHCPv6 协议来从 DHCPv6 服务器端租赁 IPv6 地址。

    在有状态自动配置 IPv6 地址时,DHCPv6 服务端可以通过客户端设置的 vendor class 将客户端进行分类,不同类别分配不同地址段的 IPv6 地址。在 IPv4 场景中,客户端可以直接用 dhclient的-V 选项来设置 vendor-class-identifier,DHCP 服务端在配置文件中根据 vendor-class-identifier 来对客户端进行分类处理。而 IPv6场景中,如果使用同样的方法对客户端分类,则分类并不会生效。

    dhclient -6 <interface> -V <vendor-class-identifier string> <interface>
    

    这是由于 DHCPv6 和 DHCP 协议存在较大差异,DHCPv6 的可选项中使用 vendor-class-option 替代了 DHCP 中的 vendor-class-identifier。而 dhclient 的-V 选项并不能设置 vendor-class-option。

有状态自动配置 IPv6 地址时 dhclient 设置 vendor class 方法

  • 在客户端使用配置文件方式添加对 vendor class 的设置,使用方法如下:

    客户端配置文件(/etc/dhcp/dhclient6.conf),文件位置可以自定义,在使用时需要通过 dhclient -cf 选项来指定配置文件:

    option dhcp6.vendor-class code 16 = {integer 32, integer 16, string};
    interface "enp3s0" {
            send dhcp6.vendor-class <Enterprise-ID number> <vendor class string length> <vendor class string>;
    }
    

    说明:

    - 32位整型数字,企业标识号,企业通过 IANA 注册。

    - 16位整型数字,vendor class 字符串长度。

    - 要设置的 vendor class 字符串,例如:“HWHW”。

    客户端使用方法:

    dhclient -6 <interface> -cf /etc/dhcp/dhclient6.conf
    
  • DHCPv6 服务端配置文件(/etc/dhcp/dhcpd6.conf),需要 dhcpd -cf 选项来指定该配置文件:

    option dhcp6.vendor-class code 16 = {integer 32, integer 16, string};
    subnet6 fc00:4:12:ffff::/64 {
            class "hw" {
                    match if substring ( option dhcp6.vendor-class, 6, 10 ) = "HWHW";
            }
            pool6 {
                    allow members of "hw";
                    range6 fc00:4:12:ffff::ff10 fc00:4:12:ffff::ff20;
            }
            pool6 {
                    allow unknown clients;
                    range6 fc00:4:12:ffff::100 fc00:4:12:ffff::120;
            }
    }
    

    说明:

    substring ( option dhcp6.vendor-class, 6, 10 ) 其中子字符串的开始位置为6,因为前面包含4个字节的和2个字节的。而子字符串的结束位置位:6+。这里 vendor class string 为“HWHW”,字符串的长度为4,所以子字符串的结束位置为 6+4=10。用户可以根据实际需要来确定及相应的。

服务端使用方法:

  dhcpd -6 -cf /etc/dhcp/dhcpd6.conf <interface>

内核支持 socket 相关系统调用

概述

IPv6 地址长度扩展到 128 比特,所以有足够的 IPv6 地址可供分配使用。同时 IPv6 头相比 IPv4 头进行了简化,并增强了 IPv6 的自动配置功能。IPv6 地址分为单播地址,组播地址和任意播地址。常用的单播地址又包含:链路本地地址(link-local address),唯一本地地址(Unique local address)和全局地址(global address)。由于 IPv6 的全局地址十分充足,唯一本地地址一般不被使用(其前身为站点本地地址(site-local address),已于 2004 年被废弃)。当前主要使用的单播地址为:链路本地地址(link-local address)和全局地址(global address)。当前内核支持 socket 系统调用,在使用单播地址的链路本地地址和全局地址时存在差异。

RFC 2553: Basic Socket Interface Extensions for IPv6 定义 sockaddr_in6 的数据结构如下;

struct sockaddr_in6 {     
    uint8_t         sin6_len;       /* length of this struct */     
    sa_family_t     sin6_family;    /* AF_INET6 */     
    in_port_t       sin6_port;      /* transport layer port # */     
    uint32_t        sin6_flowinfo;  /* IPv6 flow information */     
    struct in6_addr sin6_addr;      /* IPv6 address */     
    uint32_t        sin6_scope_id;  /* set of interfaces for a scope */ 
};

说明:

sin6_scope_id: 32 位整型,对于链路本地地址(link-local address),对于链路范围的 sin6_addr,它可以用来标识指定的接口索引号。如果是站点范围的 sin6_addr,则用来作为站点的标识符(站点本地地址已被抛弃)。

在使用 link-local 地址进行 socket 通信时,在构造目的地址时,需要制定该地址所对应的接口索引号。一般可以通过 if_nametoindex 函数将接口名转化为接口索引号。具体方式如下,

int port = 1234;
int sk_fd;
int iff_index = 0;
char iff_name[100] = "enp3s0";
char * ll_addr[100] = "fe80::123:456:789";
struct sockaddr_in6 server_addr;

memset(&server_addr,0,sizeof(structsockaddr_in6));
iff_index=if_nametoindex(iff_name);

server_addr.sin6_family=AF_INET6;
server_addr.sin6_port=htons(port);
server_addr.sin6_scope_id=iff_index;
inet_pton(AF_INET6, ll_addr, &(server_addr.sin6_addr));

sk_fd=socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
connect(sk_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in6));

IPv4 的 dhclient 守护进程持久化配置

概述

通过 NetworkManager 服务来管理网络服务时,如果接口 ifcfg- 配置文件中配置了 DHCP 方式获得IP地址,则相应地 NetworkManager 服务会拉起 dhclient 守护进程来通过 DHCP 协议方式来从 DHCP 服务器获取IP地址。

dhclient 提供了”-1”选项来决定 dhclient 进程在未获得 DHCP 服务响应时,是会不断持久化尝试请求地址还是会尝试时间超时后退出。针对IPv4的 dhclient 守护进程,可以在 ifcfg- 配置文件中设置 PERSISTENT_DHCLIENT 来决定是否设置IPv4的 dhclient 进程的持久化。

约束限制

  1. 当 dhclient 进程在运行中被杀死,network 服务无法自动将其拉起,可靠性需要用户自己保障。
  2. 配置了持久化选项 PERSISTENT_DHCLIENT,需要确保有相应的DHCP服务器。如果在拉起 network 时无可用 DHCP 服务器,dhclient 进程不断尝试发送请求包但无回应,则会导致 network 服务卡死直到 network 服务超时失败。由于 network 服务在拉起多个网卡的 IPv4 dhclient 进程时,是通过串行的方式来拉起的。如果有网卡配置了持久化而 DHCP 服务器没有准备好,则会导致 network 服务在给该网卡获取 IPv4 地址超时卡死,进而导致后续网卡无法获得 IPv4/IPv6 地址。

以上两种约束限制是特殊的应用场景,需要用户自己进行可靠性保障。

IPv4 DHCP和IPv6 DHCPv6 方式获取地址的配置差异

可以通过配置接口 ifcfg- 参数来分别实现 IPv4 和 IPv6,通过 DHCP/DHCPv6 协议来动态获取IP地址,具体配置说明如下;

BOOTPROTO=none|bootp|dhcp
DHCPV6C=yes|no
PERSISTENT_DHCLIENT=yes|no|1|0
  • BOOTPROTO: none 表示静态配置 IPv4 地址,bootp|dhcp 则会拉起 DHCP dhclient 来动态获取 IPv4 地址。

  • DHCPV6C: no 表示静态配置 IPv6 地址,yes 则会拉起 DHCPv6 dhclient 来动态获取 IPv6 地址。

  • PERSISTENT_DHCLIENT:no|0 表示 IPv4 的 dhclient 进程配置为“非持久化”,当 dhclient 向 DHCP 服务器发送一次请求报文而无响应,则会间隔一段时间后退出,退出值为 2。yes|1 则表示 IPv4 的 dhclient 进程配置为“持久化”,dhclient 会向 DHCP 服务器反复发送请求报文。如果没有配置 PERSISTENT_DHCLIENT 项,则 IPv4 的 dhclient 会默认设置为“持久化”

    说明:

    PERSISTENT_DHCLIENT 配置只针对 IPv4 生效,对 IPv6 相关 dhclient -6 进程不生效,IPv6 默认不进行持久化配置。

iproute 相关命令配置 IPv4 与 IPv6 时的差异说明

概述

由于 IPv4 和 IPv6 是两个不同的协议标准,iproute 相关命令在使用方法上存在一定的差异。本章节主要梳理 iproute 包中用户经常使用到命令在 IPv4 和 IPv6 使用方面的差异,从而可以更好地指导用户使用 iproute 包中相关命令。

IPv6 地址的生命周期

IPv6 状态 解释
tentative 临时状态:刚添加地址还处于地址重复检测 DAD 过程
preferred 首选状态:完成 DAD 过程,没有收到相应的 NA 报文,表示该地址没有冲突。
deprecated 弃用状态:地址有一定的使用时限(valid_lft和preferred_lft),preferred_lft 到期后地址会变化 deprecated 状态。该状态下的地址不能用于创建新的连接,但是原有的连接可以继续使用。
invalid 无效状态:使用时限超过 preferred_lft 一段时间后仍然没有成功进行租约续约,则 valid_lft 时间到后地址状态会被设置为 invalid,表示该地址不可以再被使用。

其它说明:

  • preferred_lft:preferred lifetime,地址为首选状态的寿命,preferred_lft 没有到期的地址可以用于正常通信使用,若有多个 preferred 地址则按照内核具体机制选择地址。
  • valid_lft: valid lifetime,地址有效的寿命,在[preferred_lft, valid_lft]时间段内该地址不能被用于新建连接,已经创建的连接继续有效。

命令:

ip link set IFNAME mtu MTU

IPv6 中 PMTU 的最小值为 1280,如果 mtu 值设置小于 1280 则会导致 IPv6 地址丢失。其它设备无法 ping 通该 IPv6 地址。

ip addr 命令

  1. 命令:

    ip [-6] addr add IFADDR dev IFNAME
    

    添加 IPv6 地址可以选择添加 -6 选项也可以不添加,ip addr 命令会根据具体地址类型来判断是 IPv4 地址还是 IPv6 地址。

    如果指定“-6”选项,但是 IFADDR 是 ipv4 地址则会有错误返回。

  2. 命令:

    ip [-6] addr add IFADDR  dev IFNAME [home|nodad]
    

    [home|nodad] 选项只针对 IPv6 地址有效。

    • home:将该地址指定为 RFC 6275 中定义的家庭地址。(这是移动节点从家庭链路获取的地址, 是移动节点的永久地址,如果移动节点保持在相同的归属链路中,则各种实体之间的通信照常进行。)
    • nodad:配置该项(仅限IPv6)添加此地址时不执行重复地址检测 DAD(RFC 4862)。如果一台设备上多个接口通过 nodad 配置了多个相同的 IPv6 地址,则会按照接口顺序使用该 IPv6 地址。同一个接口上不能添加一个 nodad 一个非 nodad 的相同 IPv6 地址。因为两个地址是一样的,所以会报“RTNETLINK answers: File exists”。
  3. 命令:

    ip [-6] addr del IFADDR dev IFNAME
    

    删除 IPv6 地址可以选择添加 -6 选项也可以不添加,ip addr del 命令会根据具体地址类型来判断是 IPv4 地址还是 IPv6 地址。

  4. 命令:

    ip [-6] addr show dev IFNAME [tentative|-tentative|deprecated|-deprecated|dadfailed|-dadfailed|temporary]
    
    • 不指定 -6 选项,则会同时打印 IPv4 和 IPv6 地址。指定 -6 选项则只打印 IPv6 地址。
    • [tentative|-tentative|deprecated|-deprecated|dadfailed|-dadfailed|temporary],这些选项只针对 IPv6,可以根据 IPv6 地址状态对地址进行筛选查看。
      1. tentative:(仅限 IPv6)仅列出尚未通过重复地址检测的地址。
      2. -tentative:(仅限 IPv6)仅列出当前未处于重复地址检测过程中的地址。
      3. deprecated:(仅限 IPv6)仅列出已弃用的地址。
      4. -deprecated:(仅限 IPv6)仅列出未弃用的地址。
      5. dadfailed:(仅限 IPv6)仅列出重复地址检测失败的地址。
      6. -dadfailed:(仅限 IPv6)仅列出未重复地址检测失败的地址。
      7. temporary:(仅限 IPv6)仅列出临时地址

ip route 命令

  1. 命令:

    ip [-6] route add ROUTE [mtu lock MTU]
    
    • -6 选项:添加 IPv6 路由可以选择添加 -6 选项也可以不添加,ip route 命令会根据具体地址类型来判断是 IPv4 地址还是 IPv6 地址。
    • mtu lock MTU:锁定路由的 MTU 值。如果不锁定 MTU,则 MTU 的值则可能在 PMTUD 过程中被内核改变。如果锁定 MTU,则不会尝试 PMTUD,所有 IPv4 包都将不设置 DF 位发出,IPv6 包则会按照 MTU 进行分段处理。
  2. 命令:

    ip [-6] route del ROUTE
    

    删除 IPv6 路由可以选择添加 -6 选项也可以不添加,ip route 命令会根据具体地址类型来判断是 IPv4 地址还是 IPv6 地址。

ip rule 命令

  1. 命令:

    ip [-6] rule list
    

    -6 选项:设置 -6 选项打印 IPv6 的策略路由,不设置 -6 选项打印 IPv4 的策略路由。所以需要根据具体协议类型来配置 -6 选项。

  2. 命令:

    ip [-6] rule [add|del] [from|to] ADDR table TABLE pref PREF
    

    -6 选项:IPv6 相关的策略路由表项需要设置 -6 选项,否则会报错:“Error: Invalid source address.”。相应地,IPv4 相关的策略路由表项不可以设置 -6 选项,否则会报错:“Error: Invalid source address.”。

NetworkManager 服务配置差异说明

概述

NetworkManager 服务使用 ifup/ifdown 的逻辑接口定义进行高级网络设置。其参数大多数都是在 /etc/sysconfig/network和/etc/sysconfig/network-scripts/ifcfg- 两个配置文件设置。前者为全局设置,后者为指定网卡的设置,当两者有冲突时,后者生效。

配置差异说明

其中在 /etc/sysconfig/network 下的配置差异有:

IPv4 IPv6 含义说明
NA IPV6FORWARDING=yes|no IPv6 转发,默认不转发。
NA IPV6_AUTOCONF=yes|no IPv6 转发打开是 no,否则是 yes。
NA IPV6_ROUTER=yes|no IPv6 转发打开是 yes,否则是 no。
NA IPV6_AUTOTUNNEL=yes|no 指定 Tunnel 为自动隧道模式,默认是 no。
GATEWAY IPV6_DEFAULTGW=<IPv6 address[%interface]>(optional) 在 IPv6 中设置默认网关。
NA IPV6_DEFAULTDEV=<interface> (optional) 指定默认转发的网卡。
NA IPV6_RADVD_PIDFILE=<pid-file> (optional) 默认 ipv6_radvd_pid 路径:/var/run/radvd/radvd.pid。
NA IPV6_RADVD_TRIGGER_ACTION=startstop|reload|restart|SIGHUP (optional) radvd 默认触发动作。

而在 /etc/sysconfig/network-scripts/ifcfg- 下的差异主要有:

IPv4 IPv6 含义说明
IPADDRn IPV6ADDR=<IPv6 address>[/<prefix length>] ip 地址。
PREFIXn NA 网络前缀,网络别名和 ppp 无效,优先级高于 NETMASK。
NETMASKn NA 子网掩码,仅用于别名和 ppp。
GATEWAY IPV6_DEFAULTGW=<IPv6 address[%interface]> (optional) 默认网关。
MTU IPV6_MTU=<MTU of link> (optional) 默认 MTU。
IPV4_FAILURE_FATAL=yes|no IPV6_FAILURE_FATAL 默认值是 no。若设置为 yes,dhclient 失败 ifup-eth 会直接退出。
NA IPV6_PRIVACY=rfc3041 默认禁用。
NA IPV6INIT=yes|no 默认开启 IPv6。
NA IPV6FORWARDING=yes|no 默认关闭,已废弃。

FAQ

iscsi-initiator-utils 不支持登录 fe80 IPv6 地址

问题现象

客户端通过 IPv6 登录 iscsi 服务端时,使用如“iscsiadm -m node -p ipv6address -l”的命令格式登录,如果是全局地址(global address),直接替换将命令范例中的“ipv6address”替换为全局地址即可;但如果是链路本地地址(link-local address,fe80 开头的 IPv6 地址)则无法使用,因为 iscsi-initiator-utils 目前机制还不支持用链路本地地址(link-local address)地址登录 iscsi 服务端。

原因分析

如果使用格式如“iscsiadm -m node -p fe80::xxxx -l”登录,会登录超时返回,这是因为使用链路本地地址必须指定接口,否则使用 iscsi_io_tcp_connect 函数调用 connect 函数会失败,并且产生标准错误码22。

如果使用格式如“iscsiadm -m node -p fe80::xxxx%enp3s0 -l”登录时,iscsi_addr_match 函数会将地址“fe80::xxxx%enp3s0”与服务端返回的node信息中的地址“fe80::xxxx”对比,对比结果不匹配,导致登录失败。

因此,iscsi-initiator-utils 目前机制还不支持用链路本地地址(link-local address)地址登录 iscsi 服务端

网卡 down 掉之后,IPv6 地址丢失

问题现象

通过 ip link down+up 网卡或 ifconfig down+up 网卡命令,将网卡 down 掉之后再上线,查看网卡上配置的 ip 地址,发现 IPv4 地址不丢失,而配置的 IPv6 地址丢失。

原因分析

内核中的处理逻辑为如果网卡设置为 down 状态,会清空所有 IPv4 及 IPv6 地址,将网卡重新 up 之后,IPv4 地址自动恢复,网卡上自动配置的 IPv6 链路本地地址也会恢复,但是其他 IPv6 地址默认会丢失。如果需要保留这些 IPv6 地址,可以通过“sysctl -w net.ipv6.conf.<网卡名>.keep_addr_on_down=1”来实现。

bond 口已具有多个 IPv6 地址时,添加或删除 IPv6 地址耗时过久

问题现象

下列方式配置或删除(包括flush)IPv6 地址方式,X 为动态变化的低 16 位,并且配置在 bond 口时,耗时会随已配置的 IPv6 地址数量成数倍增加。例如由 4 个物理网卡组成的 bond 口添加 IPv6 地址时,单线程添加删除 3000 IPv6 地址均需大概 5 分钟,而普通物理网卡耗时在 10 秒内。

ip a add/del 192:168::18:X/64 dev DEVICE

原因分析

bond 口在添加 IPv6 地址时,会生成 IPv6 组播地址,并进行同步到所有的物理网卡上,此耗时会随 IPv6 数量增加而增加,导致耗时过长。

解决方法

IPv6 的组播地址是由 IPv6 地址的低 24 位与 33-33-ff 组合生成,组播地址过多会导致添加删除耗时增加,如果生成的组播地址为少量,耗时不会受此影响。

建议添加 IPv6 地址时,可保持低 24 位一致,保持高位变动,单网卡中仅需一个网段的一个地址即可与外部正常通信,此配置更符合常规使用。

Rsyslog 在 IPv4 和 IPv6 混合使用场景中日志传输延迟

问题现象

rsyslog 客户端配置文件同时配置 IPv4 和 IPv6 地址,且端口配置相同的情况下,服务端收集 log 时会概率性出现日志打印延迟。

原因分析

延迟是因为 rsyslog 内部存在缓冲队列机制,默认情况下需要缓冲区队列达到一定数量才会写入文件。

解决方法

可通过配置 Direct 模式,关闭缓冲队列机制解决该问题。在 rsyslog 远程传输服务端的 /etc/rsyslog.d 目录下新增的远程传输配置文件中,最开头增加如下配置:

$ActionQueueType Direct
$MainMsgQueueType Direct

说明:

- Direct 模式减少队列大小为 1,所以在队列中会保留 1 条日志到下次日志打印;

- Direct 模式会降低服务器端的 rsyslog性能。

results matching ""

    No results matching ""