- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在编写自己的 DNS 黑洞来阻止我家庭网络上的广告和恶意软件。我意识到这种类型的程序已经存在,但我想学习这个过程并编写自己的程序。从 Linux 文档来看,似乎可以告诉 sendmsg() 使用不同的返回地址,以便可以转发 UDP 数据包,接收服务器会将响应发送给原始请求者而不是我的服务器。从稀疏文档中,我设置了绑定(bind)到端口 53 (DNS) 的套接字。我正在接收 DNS 请求,解释它们并在网站被列入黑名单时做出响应。对于“好”域名,我得到了 2 个不同的结果。在 MacOS 上,我的转发请求已发送,但响应返回到我的程序而不是原始请求者。在 Linux(Armbian 4.13 内核)上,我从 sendmsg() 调用中获得 EINVAL,但没有发送任何内容。任何人都可以阐明我做错了什么吗? (为简洁起见,已删除所有错误检查)
其他信息...此方案中的一个问题是原始 DNS 请求绑定(bind)到 53 以外的套接字端口(很明显)。我如何告诉 sendmsg() 将响应返回到原始请求的正确端口号?
我的“代理”版本有效。我存储了原始请求的交易 ID 和请求端口号,并且能够成功返回响应
最新消息 - 我能够成功完成我想要的,但没有使用 sendmsg()。通过使用 RAW 套接字并“欺骗”IP header 中的返回地址,我能够将数据包发送回不同的返回地址和端口号(使用 sendto)。 nslookup 认为这是一个问题,但浏览器可以接受。我想我们可以称此为“结案”
struct sockaddr_in addr, addrfrom, fwaddr;
socklen_t addrLen = sizeof(struct sockaddr_in);
int rc, listen_sock;
listen_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
rc = 1;
setsockopt(listen_sock, IPPROTO_IP, IP_PKTINFO, &rc, sizeof(rc));
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(53); // port address of DNS
addr.sin_addr.s_addr = INADDR_ANY;
bind(listen_sock, (struct sockaddr*)&addr, sizeof(addr));
memset(&fwaddr, 0, sizeof(fwaddr));
fwaddr.sin_family = AF_INET;
fwaddr.sin_port = htons(53);
fwaddr.sin_addr.s_addr = 0x08080808; // Google DNS server
<... Receive DNS request from client...>
if (bForward)
{
struct msghdr msg;
struct iovec iov[1];
struct {
struct cmsghdr cm; /* this ensures alignment */
struct in_pktinfo ipi;
} cmsg;
memset(&cmsg, 0, sizeof(cmsg));
memset(&msg, 0, sizeof(msg));
iov[0].iov_base = request_bufffer;
iov[0].iov_len = request_len;
msg.msg_flags = 0;
msg.msg_name = &fwaddr; // dest address of packet
msg.msg_namelen = addrLen;
msg.msg_iov = &iov[0];
msg.msg_iovlen = 1;
msg.msg_control = &cmsg;
msg.msg_controllen = sizeof(cmsg); //sizeof(struct in_pktinfo);
cmsg.cm.cmsg_len = sizeof(cmsg);
cmsg.cm.cmsg_level = IPPROTO_IP;
cmsg.cm.cmsg_type = IP_PKTINFO;
cmsg.ipi.ipi_ifindex = 0;
cmsg.ipi.ipi_spec_dst = addrfrom.sin_addr; // original source address
rc= sendmsg(listen_sock, &msg, 0);
} // bForward
最佳答案
我发现这段代码中有 2 个潜在问题。
首先,我会使用类似 this SO answer 的代码来修复您的消息结构.我怀疑您应该仔细查看 in_pktinfo
的偏移量和您传递给 cmsg_len
的长度,因为这些可能会导致 EINVAL 错误。一种可能的策略可能是将代码缩减到它只是正常发送数据包以查看哪些数据结构被拒绝的程度。
如果这样做不行,我想您可以考虑重写您的发送逻辑以使用原始套接字来绕过您的内核可能正在执行的任何 IP 验证。例如,this code看起来应该大致就是您所需要的。
如果这还不够,我怀疑您需要在内核安全系统中进行路由。
关于linux - UDP 数据包转发从 sendmsg 获取 EINVAL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46984389/
我在极少数情况下看到 pthread_cond_timedwait() 返回 EINVAL 并导致我们的系统发生致命崩溃。我知道这意味着传入的参数之一必须无效,但是 mutex 或 cond 变量如何
我正在尝试使用 aio_write(1) 函数。下面的代码是我的程序。但是,aio_write() 总是返回 EINVAL。 看了EINVAL的错误原因:aio_offset、aio_reqprio、
我们正在从 ARM 嵌入式 Ubuntu 14.04 更新到 ARM 嵌入式 Ubuntu 16.04。在第一个平台上,我们可以毫无问题地访问使用 SPIDEV 的芯片。在 Ubuntu 平台上,我在
我有以下两个功能: static int MessAttrManager_inotifyUnregister(MessPropertyManager* base, int wd){ MessAtt
我正在尝试弄清楚如何正确使用 tee。在我的应用程序中,tee 出于某种原因总是返回 EINVAL。我感到绝望,并尝试运行 tee 手册页中列出的示例应用程序(例如:https://linux.die
我无法使 mmap 函数工作。它返回 EINVAL 错误代码。 void* mapped = mmap((void*)(map_addr + slide),
我正在尝试调试一个问题,但我不明白。 func BackgroundProcess(lpCommandLine string) (error) { var lpProcessAttrs win
我正在使用为以下问题提供的代码 numa+mbind+segfault ,每次调用 mbind 都会返回 EINVAL。我怎样才能得到什么是完全错误的?我问这个是因为有很多原因可以返回 EINVAL。
我正在尝试在 C 中发送一个 UDP 数据包。我有以下 sendto(): char* msg = "Hello"; //ret is the return value of getaddrinfo,
我正在尝试下载一个 ~2GB 的文件并将其写入本地文件,但我遇到了这个问题: 这是适用的代码: File.open(local_file, "wb") do |tempfile| puts
我在闪存驱动器 E 上使用 Node v11.5 和 npm 6.4.1,在 win 7 上,我正在尝试安装最新的 netlify cli。关注 https://cli.netlify.com/get
我是新人,我有一个问题。在android中,我无法通过TCP套接字连接任何远程地址。当我尝试连接时,调试器显示错误: Exception: failed to connect to /23.20.47
我修改了this C数据报(UDP)套接字客户端示例: #include #include #include #include #include #include #include #i
我有一个 C-ZMQ 客户端,它接收两个随机端口(来自 pyzmq 服务器),然后连接到它们。 通常情况下,一切正常,但有时第二次连接会失败,errno 设置为 EINVAL。 (即使我在连接调用之间
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我正在尝试使用 setsockopt 函数将地址添加到接口(interface)的多播地址列表中,但失败并显示错误号 EINVAL。我在内核代码中放置了一些 printk,看起来 errno 最终是在
我正在尝试绑定(bind)服务器套接字,以便我可以接收和监听来自其他客户端的传入消息。但我无法绑定(bind),它返回错误 - EINVAL(无效参数)。我已经完成了之前提出的与此错误相关的问题,Li
我正在尝试对 IO 密集型代码使用预取提示。我根据我对 gpfs_fcntl() 手册页的理解设置了代码,但确实得到了一个 EINVAL。我现在有点迷茫,我做错了什么 - 任何提示表示赞赏。 挂载
我想用以下格式的文件名创建一个文件:DAY-MONTH-YEAR--HOUR:MINUTE 但是当我使用 -- 或/and : 我遇到了 open failed: EINVAL 异常。我试图摆脱这些焦
几个小时以来我一直遇到 shmget 的问题,现在我似乎无法弄清楚。每次我尝试调用 shmget() 时,它总是返回 EINVAL: "Invalid Argument"错误。 代码的重要部分如下:
我是一名优秀的程序员,十分优秀!