#23 Wi-Fi 6 还没用上,Wi-Fi 7 又来了

2023-11-27
标准 名称 年份 频率(GHz) 理论最大速率 备注
IEEE 802.11 Wi-Fi 0 1997 2.4 2 Mbps
IEEE 802.11b Wi-Fi 1 1999 2.4 11 Mbps
IEEE 802.11a Wi-Fi 2 1999 5 54 Mbps 正交频分复用(OFDM)
IEEE 802.11g Wi-Fi 3 2003 2.4 54 Mbps 正交频分复用(OFDM),兼容 802.11b
IEEE 802.11i 草案 WPA 2003 -- --
IEEE 802.11i-2004 WPA 2 2004 -- --
IEEE 802.11n Wi-Fi 4 2009 2.4/5 600 Mbps 最多 4 个 MIMO
IEEE 802.11ac Wi-Fi 5 2014 5 最多 8 个 MIMO;下行 MU-MIMO (2016 Wave2)
IEEE 802.11i-2018 WPA 3 2018 -- --
IEEE 802.11ax Wi-Fi 6 2019 2.4/5 9.6 Gbps 上下行 MU-MIMO
Wi‑Fi 6E 2020 6
IEEE 802.11be Wi-Fi 7 2024 2.4/5/6 23 Gbps
  • 802.11a 其实早于 802.11b 提出,只是因为一些非技术原因,推广滞后
  • 2000 年,Wi-Fi 这个词被提出,无线以太网兼容性联盟(WECA)更名为 Wi-Fi 联盟(Wi-Fi Alliance,缩写 WFA)
  • Wi-Fi 一词,国内通常读作 歪fai,有一些人引经据典提出过不同看法引发争议
  • Wi-Fi 0、1、2、3 不是官方认定的名称
  • WEP:有线等效加密(Wired Equivalent Privacy),又称无线加密协议(Wireless Encryption Protocol)
  • WPA:Wi-Fi Protected Access (Wi-Fi 访问保护)

现状

市面上大部分路由器都是支持 Wi-Fi 1 - 5,常常可以在广告上看到 IEEE 802.11a/b/g/n/ac 字样。
旗舰型,贵一点的(至少 300+),支持 Wi-Fi 6。

我没有做过这方面研究和对比,只能说理论上:

  1. Wi-Fi 6 速率上限有了提升,网络质量也有优化,同时能耗降低(TWT),能够同时支持更多终端连接(OFDMA),同时支持更多并发数据传输(MU-MIMO)。
  2. Wi-Fi 6E 引入了 6GHz 频段,能支持更高的速度和更低的延迟。

目前我家的路由器,手机,其他设备大多还不支持 Wi-Fi 6。
我家的有线网络用的 5 类线,所以我家理论上最高网速也就 100Mbps(12MB/s)。

Wi-Fi 7

  1. 支持最大 320MHz 带宽(Wi-Fi 6 是 160MHz)
    新的带宽模式:连续 240MHz、非连续 160+80MHz、连续 320 MHz、非连续 160+160MHz
    主要作用是提升 QoS(减少延迟,降低丢包率)
  2. 支持 Multi-RU 机制
  3. 引入更高阶的 4096-QAM 调制技术(Wi-Fi 6 是 1024-QAM)
  4. 引入 Multi-Link 多链路机制
  5. 支持多 AP 间的协同调度
    网络漫游问题

我不太懂。
场景应该是一些工业和商业场景。家用的话,可能只有土豪的游戏设备(VR 游戏?)才能用得上,或者发烧友自己搭建的家庭网络设施。
想必和 Wi-Fi 6 / 5G 一样,对绝大多数普通人来说,只是一个新的营销噱头。

参考资料与拓展阅读

Wi-Fi(发音: /ˈwaɪfaɪ/),又称“无线网络”,是 Wi-Fi 联盟的商标,一个基于 IEEE 802.11 标准的无线局域网技术。“Wi-Fi”常写作“WiFi”或“Wifi”,但是这些写法并没有被 Wi-Fi 联盟认可。

1999 年,几家富有远见的公司联合起来组成了一个全球性非营利性协会——无线以太网兼容性联盟(Wireless Ethernet Compatibility Alliance, WECA),其目标是使用一种新的无线网络技术,无论品牌如何,都能带来最佳的用户体验。在 2000 年,该小组采用术语“Wi-Fi”作为其技术工作的专有名称,并宣布了正式名称:Wi-Fi Alliance。

第七代 WiFi 无线网络,速度可高达 30Gbps,是 WiFi 6 最高 9.6Gbps 速率的三倍之多。相比于 Wi-Fi 6,WiFi 7 将引入 CMU-MIMO 技术最多可支持 16 条数据流,8 车道变 16 车道,妥妥的星际高速公路,其次 WiFi 7 除传统的 2.4GHz 和 5GHz 两个频段,还将新增支持 6 GHz 频段,并且三个频段能同时工作。
2021 年 12 月,联发科宣布 2022 年初将推出 WiFi 7 网络,此前数据显示其网速是 Wi-Fi 6 的 3 倍多。在 2022 年世界移动通信大会(MWC 2022)上,中兴推出 WiFi 7 标准的产品。

#20 ping github.com 得到 127.0.0.1 问题

2022-10-27
git clone git@github.com:tornado/tornado
Cloning into 'tornado'...
ssh: connect to host github.com port 22: Connection refused
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
ping github.com

正在 Ping github.com [::1] 具有 32 字节的数据:
来自 ::1 的回复: 时间<1ms
来自 ::1 的回复: 时间<1ms
来自 ::1 的回复: 时间<1ms

::1 的 Ping 统计信息:
    数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 0ms,最长 = 0ms,平均 = 0ms
Control-C
ping -4 github.com

正在 Ping github.com [127.0.0.1] 具有 32 字节的数据:
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=64
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=64
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=64

127.0.0.1 的 Ping 统计信息:
    数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 0ms,最长 = 0ms,平均 = 0ms
Control-C
nslookup github.com
Server:         192.168.31.1
Address:        192.168.31.1#53

Non-authoritative answer:
Name:   github.com
Address: 127.0.0.1
Name:   github.com
Address: ::1

配置 DNS 为 AliDNS 223.5.5.5233.6.6.6

nslookup github.com
Server:         223.5.5.5
Address:        223.5.5.5#53

Non-authoritative answer:
Name:   github.com
Address: 20.205.243.166

问题依旧。

ping 20.205.243.166

正在 Ping 20.205.243.166 具有 32 字节的数据:
请求超时。
请求超时。
请求超时。

20.205.243.166 的 Ping 统计信息:
    数据包: 已发送 = 3,已接收 = 0,丢失 = 3 (100% 丢失),
Control-C
ping baidu.com

正在 Ping baidu.com [39.156.66.10] 具有 32 字节的数据:
来自 39.156.66.10 的回复: 字节=32 时间=23ms TTL=52
来自 39.156.66.10 的回复: 字节=32 时间=24ms TTL=52
来自 39.156.66.10 的回复: 字节=32 时间=23ms TTL=52

39.156.66.10 的 Ping 统计信息:
    数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 23ms,最长 = 24ms,平均 = 23ms
Control-C

总结

  1. hosts 没有特殊配置
  2. 改成可用 DNS,问题没有修复
  3. ipconfig /flushdns 也不管用
  4. 重启也没有好

那就奇怪了,这个 ping 里面的本地回环地址是哪里来的呢?

最后,

ipconfig /displaydns 可以看到,还是用的回环地址
ipconfig /all 发现还有一个 DNSv6 配置。。。

DNSv6 设置成 AliDNS 的 IPv6 地址:2400:3200::12400:3200:baba::1 再试,

ping github.com

正在 Ping github.com [20.205.243.166] 具有 32 字节的数据:
请求超时。
请求超时。
请求超时。
请求超时。

20.205.243.166 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 0,丢失 = 4 (100% 丢失),

终于好了。😂

事情的起源是 git clone 失败,最后 git clone 可以了。
ping 不通,可能是网络问题,也可能是 github 网络配置。
这就不管了。

#19 办公网络中的安全问题

2022-04-14

同事发来消息,说是我的电脑经过安全扫描,判断有风险。提了以下几条改进意见:

  1. SMB 共享,风险高,希望限制访问,并强制执行消息签名。
    改进:其实现在我很少使用 SMB 共享了,直接关闭了事。
    PS: 其实在用 SMB 共享,所以重新开启 smbd 并禁止匿名访问。

  2. 开启了 IP 转发,风险中,建议关闭。
    IP 转发功能对我的工作是非常必要的,不能关闭
    之前的文章, 2021/05/09, VPN 与 NAT 有讲过这个问题。
    改进:调整 iptables 规则,only ACCEPT 指定链路 FORWARD

  3. 3Proxy HTTP 代理(端口 10809)只做透明请求远程溢出,风险高,建议升级 3Proxy 版本。
    我没有安装什么 3Proxy, 这个端口是其他 HTTP 代理服务的端口(不排除底层使用了 3Proxy)
    改进:我直接将其改成监听 127.0.0.1 了事

#17 IPv6 地址

2021-12-30
$ ip -c -6 addr show dev wlp6s0
3: wlp6s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet6 2409:8a4d:c81:c140::5/128 scope global dynamic noprefixroute
       valid_lft 226977sec preferred_lft 140577sec
    inet6 2409:8a4d:c81:c140:ca67:f46:7f29:1dad/64 scope global temporary dynamic
       valid_lft 376sec preferred_lft 376sec
    inet6 2409:8a4d:c81:c140:fcf0:3456:fac4:3b63/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 376sec preferred_lft 376sec
    inet6 fe80::56f8:128b:b513:e571/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
# ipconfig /all
# ipconfig

无线局域网适配器 WLAN:

   连接特定的 DNS 后缀 . . . . . . . :
   IPv6 地址 . . . . . . . . . . . . : 2409:8a4d:c81:c140::6
   IPv6 地址 . . . . . . . . . . . . : 2409:8a4d:c81:c140:68cd:b350:9fe8:9feb
   临时 IPv6 地址. . . . . . . . . . : 2409:8a4d:c81:c140:757f:88b3:b455:5882
   本地链接 IPv6 地址. . . . . . . . : fe80::68cd:b350:9fe8:9feb%5
   IPv4 地址 . . . . . . . . . . . . : 192.168.1.7
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . : fe80::1%5
                                       192.168.1.1

   DHCP 服务器 . . . . . . . . . . . : 192.168.1.1
   DNS 服务器  . . . . . . . . . . . : 2409:804c:2000:1::1
                                       2409:804c:2000:2::1
                                       192.168.1.1

一、地址格式

IPv4 4 字节, 一般用四个十进制的数字表示,xxx.xxx.xxx.xxx 形式,每一段的范围是 0~255。
IPv6 16 字节,一般用 32 个十六进制数表示,每四个一组,共八组,xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx 形式,每一段的范围是 0000~FFFF。

缩写

  1. 高位的 0 可以省略,比如 0001 就可以写成 1
  2. 全 0 段可以省略,用分号表示,比如 fe80::, :: (全 0), 又比如上面的 2409:8a4d:c81:c140::5
    但是, 只能缩写一次,比如 A:B:0:0:C:D:0:0 不能写成 A:B::C:D::, 只能缩写成 A:B::C:D:0:0A:B:0:0:C:D::

百分号

如果一台机器有多张网卡,都有一个 fe80 的链路地址,操作系统无法区分一个包该走哪张网卡出。

在 IPv4 中,不同网卡一般配置了不同子网,比如 172.16.31.0/24, 172.168.32.0/24

但是 IPv6 的分配可以自己生成(无状态地址自动配置),大家都在 fe80 段。

百分号后面附加的是 zone index,这个数据是操作系统解释的。Windows 会采用接口号(整型数),而 Linux 习惯端口名称,比如 eth0, enp7s0。
PS: 推荐阅读: 网卡名称的变迁(ethX -> enpXsY)

  • windows: netsh interface ipv6 show address
  • linux: ifconfig

注意:用在 URL 中时,这个百分号应该转义成 %25

二、前缀

IPv4 有分区的概念,一开始叫做分类网络,ABCDE 五类。后来又有无类网络 (Classless Inter-Domain Routing, CIDR),取任意长度作前缀,比如 172.16.0.0/12 以 1010 1100 0001 做前缀。

IPv6 也有分区的概念,和 CIDR 一样,可以取任意长度作前缀。
比如 fe80::/10 就是以 1111 1110 10 做前缀。

移动网络给我分配的是 /64 段,听说有地方能拿到更短前缀(V2EX, 2020/07, 电信 IPv6 大家还能拿到/56 么)。

如果拿到更短前缀,就可以自己在家划分子网了。根据现在的实践(SLAAC),一个网络最少需要留 64 位,如果正好分的是 64 位前缀,那么就不能采用 SLAAC 方案了,只能走 DHCP。

无状态自动配置

  1. RS, Router Solicitation
  2. RA, Router Advertisement 路由器告诉机器 IPv6 前缀
  3. NS, Neighbor Solicitation 机器广播自己将要采用某一个 IPv6

#16 转载:是谁拉黑了你的 IP

2021-11-24

邮件无法送达的原因有很多,例如 取消订阅、服务器不可达、地址格式错误或不存在、被判定为垃圾邮件、发信人/收信人被拒等等等等…今天,我们来聊一下 IP、域名被拒。

#15 转载:用户态 tcpdump 如何实现抓到内核网络包的?

2021-09-08

在网络包的发送和接收过程中,绝大部分的工作都是在内核态完成的。那么问题来了,我们常用的运行在用户态的程序 tcpdump 是那如何实现抓到内核态的包的呢?有的同学知道 tcpdump 是基于 libpcap 的,那么 libpcap 的工作原理又是啥样的呢。如果让你裸写一个抓包程序,你有没有思路?

按照飞哥的风格,不搞到最底层的原理咱是不会罢休的。所以我对相关的源码进行了深入分析。通过本文,你将彻底搞清楚了以下这几个问题。

  • tcpdump 是如何工作的?
  • netfilter 过滤的包 tcpdump 是否可以抓的到?
  • 让你自己写一个抓包程序的话该如何下手?

借助这几个问题,我们来展开今天的探索之旅!

一、网络包接收过程

图解 Linux 网络包接收过程一文中我们详细介绍了网络包是如何从网卡到达用户进程中的。这个过程我们可以简单用如下这个图来表示。

找到 tcpdump 抓包点

我们在网络设备层的代码里找到了 tcpdump 的抓包入口。在 __netif_receive_skb_core 这个函数里会遍历 ptype_all 上的协议。还记得上文中我们提到 tcpdump 在 ptype_all 上注册了虚拟协议。这时就能执行的到了。来看函数:

//file: net/core/dev.c
static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
{
    ......
    //遍历 ptype_all (tcpdump 在这里挂了虚拟协议)
    list_for_each_entry_rcu(ptype, &ptype_all, list) {
        if (!ptype->dev || ptype->dev == skb->dev) {
            if (pt_prev)
                ret = deliver_skb(skb, pt_prev, orig_dev);
            pt_prev = ptype;
        }
    }
}

在上面函数中遍历 ptype_all,并使用 deliver_skb 来调用协议中的回调函数。

//file: net/core/dev.c
static inline int deliver_skb(...)
{
 return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
}

对于 tcpdump 来说,就会进入 packet_rcv 了(后面我们再说为啥是进入这个函数)。这个函数在 net/packet/af_packet.c 文件中。

//file: net/packet/af_packet.c
static int packet_rcv(struct sk_buff *skb, ...)
{
 __skb_queue_tail(&sk->sk_receive_queue, skb);
 ......
}

可见 packet_rcv 把收到的 skb 放到了当前 packet socket 的接收队列里了。这样后面调用 recvfrom 的时候就可以获取到所抓到的包!!

再找 netfilter 过滤点

为了解释我们开篇中提到的问题,这里我们再稍微到协议层中多看一些。在 ip_rcv 中我们找到了一个 netfilter 相关的执行逻辑。

//file: net/ipv4/ip_input.c
int ip_rcv(...)
{
 ......
 return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL,
         ip_rcv_finish);
}

如果你用 NF_HOOK 作为关键词来搜索,还能搜到不少 netfilter 的过滤点。不过所有的过滤点都是位于 IP 协议层的。

在接收包的过程中,数据包是先经过网络设备层然后才到协议层的。

那么我们开篇中的一个问题就有了答案了。假如我们设置了 netfilter 规则,在接收包的过程中,工作在网络设备层的 tcpdump 先开始工作。还没等 netfilter 过滤,tcpdump 就抓到包了!

所以,在接收包的过程中,netfilter 过滤并不会影响 tcpdump 的抓包!

二、网络包发送过程

我们接着再来看网络包发送过程。在25 张图,一万字,拆解 Linux 网络包发送过程一文中,我们详细描述过网络包的发送过程。发送过程可以汇总成简单的一张图。

找到 netfilter 过滤点

在发送的过程中,同样是在 IP 层进入各种 netfilter 规则的过滤。

//file: net/ipv4/ip_output.c
int ip_local_out(struct sk_buff *skb)
{
    //执行 netfilter 过滤
    err = __ip_local_out(skb);
}

int __ip_local_out(struct sk_buff *skb)
{
    ......
    return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL,
            skb_dst(skb)->dev, dst_output);
}

在这个文件中,还能看到若干处 netfilter 过滤逻辑。

找到 tcpdump 抓包点

发送过程在协议层处理完毕到达网络设备层的时候,也有 tcpdump 的抓包点。

//file: net/core/dev.c
int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq)
{
    ...
    if (!list_empty(&ptype_all))
        dev_queue_xmit_nit(skb, dev);
}

static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
{
    list_for_each_entry_rcu(ptype, &ptype_all, list) {
        if ((ptype->dev == dev || !ptype->dev) && (!skb_loop_sk(ptype, skb))) {
            if (pt_prev) {
                deliver_skb(skb2, pt_prev, skb->dev);
                pt_prev = ptype;
                continue;
            }
            ......
        }
    }
}

在上述代码中我们看到,在 dev_queue_xmit_nit 中遍历 ptype_all 中的协议,并依次调用 deliver_skb。这就会执行到 tcpdump 挂在上面的虚拟协议。

在网络包的发送过程中,和接收过程恰好相反,是协议层先处理、网络设备层后处理。

如果 netfilter 设置了过滤规则,那么在协议层就直接过滤掉了。在下层网络设备层工作的 tcpdump 将无法再捕获到该网络包

三、TCPDUMP 启动

前面两小节我们说到了内核收发包都通过遍历 ptype_all 来执行抓包的。那么我们现在来看看用户态的 tcpdump 是如何挂载协议到内 ptype_all 上的。

我们通过 strace 命令我们抓一下 tcpdump 命令的系统调用,显示结果中有一行 socket 系统调用。Tcpdump 秘密的源头就藏在这行对 socket 函数的调用里。

# strace tcpdump -i eth0
socket(AF_PACKET, SOCK_RAW, 768)
......

socket 系统调用的第一个参数表示创建的 socket 所属的地址簇或者协议簇,取值以 AF 或者 PF 开头。在 Linux 里,支持很多种协议族,在 include/linux/socket.h 中可以找到所有的定义。这里创建的是 packet 类型的 socket。

协议族和地址族:每一种协议族都有其对应的地址族。比如 IPV4 的协议族定义叫 PF_INET,其地址族的定义是 AF_INET。它们是一一对应的,而且值也完全一样,所以经常混用。

//file: include/linux/socket.h
#define AF_UNSPEC 0
#define AF_UNIX  1 /* Unix domain sockets   */
#define AF_LOCAL 1 /* POSIX name for AF_UNIX */
#define AF_INET  2 /* Internet IP Protocol  */
#define AF_INET6 10 /* IP version 6   */
#define AF_PACKET 17 /* Packet family  */
......

另外上面第三个参数 768 代表的是 ETH_P_ALL,socket.htons(ETH_P_ALL) = 768。

我们来展开看这个 packet 类型的 socket 创建的过程中都干了啥,找到 socket 创建源码。

//file: net/socket.c
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
    ......
    retval = sock_create(family, type, protocol, &sock);
}

int __sock_create(struct net *net, int family, int type, ...)
{
    ......
    pf = rcu_dereference(net_families[family]);
    err = pf->create(net, sock, protocol, kern);
}

在 __sock_create 中,从 net_families 中获取了指定协议。并调用了它的 create 方法来完成创建。

net_families 是一个数组,除了我们常用的 PF_INET( ipv4 ) 外,还支持很多种协议族。比如 PF_UNIX、PF_INET6(ipv6)、PF_PACKET 等等。每一种协议族在 net_families 数组的特定位置都可以找到其 family 类型。在这个 family 类型里,成员函数 create 指向该协议族的对应创建函数。

根据上图,我们看到对于 packet 类型的 socket,pf->create 实际调用到的是 packet_create 函数。我们进入到这个函数中来一探究竟,这是理解 tcpdump 工作原理的关键!

//file: packet/af_packet.c
static int packet_create(struct net *net, struct socket *sock, int protocol, int kern)
{
    ...
    po = pkt_sk(sk);
    po->prot_hook.func = packet_rcv;

    //注册钩子
    if (proto) {
        po->prot_hook.type = proto;
        register_prot_hook(sk);
    }
}

static void register_prot_hook(struct sock *sk)
{
    struct packet_sock *po = pkt_sk(sk);
    dev_add_pack(&po->prot_hook);
}

在 packet_create 中设置回调函数为 packet_rcv,再通过 register_prot_hook => dev_add_pack 完成注册。注册完后,是在全局协议 ptype_all 链表中添加了一个虚拟的协议进来。

我们再来看下 dev_add_pack 是如何注册协议到 ptype_all 中的。回顾我们开头看到的 socket 函数调用,第三个参数 proto 传入的是 ETH_P_ALL。那 dev_add_pack 其实最后是把 hook 函数添加到了 ptype_all 里了,代码如下。

//file: net/core/dev.c
void dev_add_pack(struct packet_type *pt)
{
    struct list_head *head = ptype_head(pt);
    list_add_rcu(&pt->list, head);
}

static inline struct list_head *ptype_head(const struct packet_type *pt)
{
    if (pt->type == htons(ETH_P_ALL))
        return &ptype_all;
    else
        return &ptype_base[ntohs(pt->type) & PTYPE_HASH_MASK];
}

我们整篇文章都以 ETH_P_ALL 为例,但其实有的时候也会有其它情况。在别的情况下可能会注册协议到 ptype_base 里了,而不是 ptype_all。同样, ptype_base 中的协议也会在发送和接收的过程中被执行到。

总结:tcpdump 启动的时候内部逻辑其实很简单,就是在 ptype_all 中注册了一个虚拟协议而已。

四、总结

现在我们再回头看开篇提到的几个问题。

1. tcpdump 是如何工作的

用户态 tcpdump 命令是通过 socket 系统调用,在内核源码中用到的 ptype_all 中挂载了函数钩子上去。无论是在网络包接收过程中,还是在发送过程中,都会在网络设备层遍历 ptype_all 中的协议,并执行其中的回调。tcpdump 命令就是基于这个底层原理来工作的。

2. netfilter 过滤的包 tcpdump 是否可以抓的到

关于这个问题,得分接收和发送过程分别来看。在网络包接收的过程中,由于 tcpdump 近水楼台先得月,所以完全可以捕获到命中 netfilter 过滤规则的包。

但是在发送的过程中,恰恰相反。网络包先经过协议层,这时候被 netfilter 过滤掉的话,底层工作的 tcpdump 还没等看见就啥也没了。

3. 让你自己写一个抓包程序的话该如何下手

如果你想自己写一段类似 tcpdump 的抓包程序的话,使用 packet socket 就可以了。我用 c 写了一段抓包,并且解析源 IP 和目的 IP 的简单 demo。

源码地址:https://github.com/yanfeizhang/coder-kung-fu/blob/main/tests/network/test04/main.c

编译一下,注意运行需要 root 权限。

# gcc -o main main.c
# ./main 

运行结果预览如下。

#14 为什么我还没有用上 IPv6?

2021-08-27
  1. IPv6 是个好东西
  2. 我们都知道 IPv6 是个好东西
  3. 我们都想用上 IPv6

那么问题来了,为什么现在还没有大规模普及 IPv6 呢?我想了半天,得到了一个答案:因为我没做好准备。

确切的说,应该是:无数个我一样的人没有做好准备。
IPv4 很简单的一串数字,虽然世界上大部分人可能都不知道它是个啥,但肯定也存在相当比例能够理解这个概念的人,这对于一项技术的普及很有必要。
但是 IPv6,我作为一个开发者都说不清楚,更别提其他普通用户了。