为啥我不能在 Ubuntu 中创建原始套接字?

Posted

技术标签:

【中文标题】为啥我不能在 Ubuntu 中创建原始套接字?【英文标题】:Why I cant create raw socket in Ubuntu?为什么我不能在 Ubuntu 中创建原始套接字? 【发布时间】:2011-10-13 04:11:24 【问题描述】:

我正在学习如何在 Linux 中使用原始套接字。我正在尝试创建一个这样的套接字:

if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) 
    perror("socket() failed");
    exit(-1);

但发布后我得到的只是:

socket() 失败:不允许操作

我知道只有 root 可以创建原始套接字,但如果我使用 SUID 位或 sudo 运行它 - 问题是一样的。怎么了?系统是Ubuntu 11.04。

也许我包含了不必要的标题?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>

我想知道 - 为什么 SUID 没用?

【问题讨论】:

有趣;试图成为真正的根? (并且在执行该行之前不会删除检查的权限?) 不,我只是调用 setuid(getuid());在套接字创建之后,但它甚至没有达到。 如果你这样做:sudo bash(或 sudo 不管你使用什么shell)然后你执行程序......?有用吗? 嗯,是的,它就是这样工作的。但是为什么suid没用呢? 您是否尝试过seteuid -- 程序上的setuid位没有设置有效的uid,可能需要以编程方式设置。 【参考方案1】:

我的钱是你没有正确运行你的代码。

我已将您的确切代码复制并粘贴到一个空的main() 中。如果我自己运行它,我会得到同样的错误,但它在sudo 下运行正确。这是在 Ubuntu 上。

代码:

#include <sys/socket.h>
#include <netinet/in.h>

int main()
 
  int sd;
  if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) 
    perror("socket() failed");
    return -1;
  
  return 0;
 

像我自己一样奔跑:

aix@aix:~$ ./a.out 
socket() failed: Operation not permitted
aix@aix:~$

以root身份运行:

aix@aix:~$ sudo ./a.out 
aix@aix:~$

【讨论】:

您的代码也可以完美运行。但是我的代码与您的代码仅在标题上有所不同。我已经包含了所有这些东西(有问题添加)。 sudoers 真正能做的事情是可配置的; sudoers 的 ubuntu 11 默认是否有可能不提供真正的 root 用户? 为我节省了不少时间。非常感谢 NPE。【参考方案2】:

根据 man:只有有效用户 ID 为 0 或具有 CAP_NET_RAW 能力的进程才能打开原始套接字

因此您可以按照下面的建议使用 sudo 运行您的应用程序,或者为其设置 CAP_NET_RAW 功能(实际上您也需要 CAP_NET_ADMIN):

# setcap cap_net_raw,cap_net_admin=eip PATH_TO_YOUR_APPLICATION

详情请见http://ftp.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.4/capfaq-0.2.txt

【讨论】:

【参考方案3】:

无论如何标题都不会影响它。

即使您要添加更多不必要的文件,也不会影响程序的运行。

【讨论】:

以上是关于为啥我不能在 Ubuntu 中创建原始套接字?的主要内容,如果未能解决你的问题,请参考以下文章

为啥数据不通过 Windows 中的原始套接字发送

c ++如何在原始抽象类中创建一个接受派生类输入的函数

在 Qt 中创建原始 GL 上下文?

如何查看用于在 phpMyAdmin 或其他程序中创建视图的原始 MySQL?

蒸汽 3,流利模型不会在 DB 中创建原始模型

如何在 C++ 中创建 RAW TCP/IP 数据包?