---
title: "Debian 双栈网络时开启 IPv4 优先"
tags: ['Debian']
published: 2022-02-10 18:17:32
updated: 2025-11-04 00:00:00
excerpt: "本文原理适用于大多数 Linux 系统，其他系统尚未测试，请读者自行验证。"
---
> 本文件是烧饼博客文章的 Markdown 原文，正式版本见 https://u.sb/debian-prefer-ipv4/
> 全站文章与页面索引见 https://u.sb/llms.txt，建议先读索引再继续抓取。

本文原理适用于大多数 Linux 系统，其他系统尚未测试，请读者自行验证。

以下操作需要 root 权限，本文命令均已带上 `sudo` 前缀，请确保当前用户拥有 `sudo` 权限；或者直接使用 root 用户操作并省略命令中的 `sudo`。

## 背景介绍

双协议栈技术就是指在一台设备上同时启用 IPv4 协议栈和 IPv6 协议栈，这样就可以同时使用 IPv4 和 IPv6 的网络。

现代操作系统和浏览器通常会优先使用 IPv6，只有当 IPv6 无法访问时，才会回退到 IPv4。但在某些特定的应用或场景中，我们可能更希望系统优先使用 IPv4，这时就需要通过配置文件进行调整。

## 修改 /etc/gai.conf

在 Debian 等 Linux 系统下，有一个 `/etc/gai.conf` 文件，用于系统的 `getaddrinfo` 调用，默认情况下，它会使用 IPv6 优先，如果您安装了 `curl` 并且本地支持 IPv6，那么可以使用 `curl ip.sb` 测试：

```bash
root@debian ~ # curl ip.sb
2001:db8::2
```

结果与 `curl ip.sb -6` 等效。

从 Debian 13 开始，curl (8.14.1) 默认强制使用 IPv6。因此，如果希望测试本地出口公网 IP，可以改用 `wget`：

```bash
root@debian ~ # wget -qO- http://ip.sb
2001:db8::2
```

效果等同于 `wget -qO- http://ip.sb -6`

如果你不想使用 IPv6 优先，可以在这个文件中找到：

```bash
#precedence ::ffff:0:0/96  100
```

取消注释，修改为：

```bash
precedence ::ffff:0:0/96  100
```

一行命令修改：

```bash
sudo sed -i 's/#precedence ::ffff:0:0\/96  100/precedence ::ffff:0:0\/96  100/' /etc/gai.conf
```

此时再次执行 `curl ip.sb` 测试：

```bash
root@debian ~ # curl ip.sb
192.0.2.2
```

效果等同于 `curl ip.sb -4`

从 Debian 13 开始的 curl (8.14.1) 会强制 IPv6 优先，所以我们可以使用 `wget` 命令：

```bash
root@debian ~ # wget -qO- http://ip.sb
192.0.2.2
```

效果等同于 `wget -qO- http://ip.sb -4`

某些情况下，你可能又需要强制启用 IPv6 优先（是的，有些系统和用户的需求确实有点奇怪😅），因为目前 IANA 分配的公网 IPv6 还未进行到 `3000:0000::/4`，所以我们只要把这段之前的 IPv6 加到优先级列表即可，加入这两行 `label` 的优先级：

```bash
label 2002::/16    1
label 2001:0::/32   1
```

## 禁用 IPv6

有一些极端情况下，我们可能需要禁止系统的 IPv6 功能，这时候就需要添加或修改 `/etc/sysctl.d/local.conf` 文件，首先找到你的网卡名称，这里以 `eth0` 为例，然后加入如下内容：

```bash
net.ipv6.conf.all.autoconf = 0
net.ipv6.conf.default.autoconf = 0
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv6.conf.eth0.disable_ipv6 = 1
```

若需对其他网卡禁用 IPv6，只需将 `eth0` 替换为对应网卡名称即可。

一句话命令

```bash
sudo bash -c 'cat >> /etc/sysctl.d/local.conf << EOF
net.ipv6.conf.all.autoconf = 0
net.ipv6.conf.default.autoconf = 0
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv6.conf.eth0.disable_ipv6 = 1
EOF'
```

注意：`cat` 命令中的 `>>` 表示追加内容；若使用 `>`，则会覆盖原有内容。

然后执行 `sudo sysctl --system` 重新加载配置文件。此时查看 `ip a`，即可发现 IPv6 已被禁用。

下图为修改前后的对比示例：

使用前，我们可以看到无论是本地还是公网网卡都有 `inet6`，即都有 IPv6 地址：

![禁用前 ip a 显示网卡带有 IPv6 地址](https://s.bh.sb/uploads/2022/02/10/oyKXC1YLbu2Mi6j.png)

使用后，无论本地还是公网网卡均无 IPv6 地址：

![禁用后 ip a 显示网卡无 IPv6 地址](https://s.bh.sb/uploads/2022/02/10/qi2nwjWeLfQXJH4.png)

## 其他系统和软件

Windows 系统可参考[这篇回答](https://superuser.com/questions/436574/ipv4-vs-ipv6-priority-in-windows-7)

Firefox 下打开 `about:config` 然后把 `network.dns.disableIPv6` 改成 `true` 即可禁止 Firefox 请求 IPv6