如何用Go语言编写代码实现发送和接收原始Socket数据包,并构造IP和TCP头部信息?
- 内容介绍
- 文章标签
- 相关推荐
本文共计942个文字,预计阅读时间需要4分钟。
在Linux/macOS系统中,非root用户默认无法创建raw socket,这是内核的强制限制,而非Go语言的bug。即使使用了`syscall.SOCK_RAW`和`syscall.IPPROTO_RAW`,在创建socket时也会因为权限不足(`EPERM`)而失败。
- 临时解决:用
sudo go run main.go(开发调试可用,但别上线) - 生产环境更稳妥的方式是给二进制加
CAP_NET_RAW能力:sudo setcap cap_net_raw+ep ./myprogram,之后普通用户就能运行 - macOS 还需额外注意:
IPPROTO_RAW不被支持,得用IPPROTO_TCP+IP_HDRINCL选项绕过,否则setsockopt会失败
syscall.SetsockoptInt 设置 IP_HDRINCL 没生效,发出去的包被内核重写 IP 头
没生效通常是因为调用时机错了——必须在 bind 之前设置,且 socket 类型得是 AF_INET + SOCK_RAW + IPPROTO_RAW(Linux)或 IPPROTO_TCP(macOS)。
本文共计942个文字,预计阅读时间需要4分钟。
在Linux/macOS系统中,非root用户默认无法创建raw socket,这是内核的强制限制,而非Go语言的bug。即使使用了`syscall.SOCK_RAW`和`syscall.IPPROTO_RAW`,在创建socket时也会因为权限不足(`EPERM`)而失败。
- 临时解决:用
sudo go run main.go(开发调试可用,但别上线) - 生产环境更稳妥的方式是给二进制加
CAP_NET_RAW能力:sudo setcap cap_net_raw+ep ./myprogram,之后普通用户就能运行 - macOS 还需额外注意:
IPPROTO_RAW不被支持,得用IPPROTO_TCP+IP_HDRINCL选项绕过,否则setsockopt会失败
syscall.SetsockoptInt 设置 IP_HDRINCL 没生效,发出去的包被内核重写 IP 头
没生效通常是因为调用时机错了——必须在 bind 之前设置,且 socket 类型得是 AF_INET + SOCK_RAW + IPPROTO_RAW(Linux)或 IPPROTO_TCP(macOS)。

