我正在使用一个守护程序,该守护程序侦听UDP广播数据包,并通过UDP进行响应。当一个包进来,我想知道哪个IP地址(或NIC)的包来到 TO
这样我就可以与该IP地址作为源地址进行响应。(出于很多麻烦的原因,我们系统的某些用户希望将同一台计算机上的两个NIC连接到同一子网。我们告诉他们不要,但是他们坚持要这样做。我不需要提醒我这是多么的丑陋。
)
似乎没有办法检查数据报并直接找出其目的地址或它进入的接口。基于大量的搜索,我发现找出数据报目标的唯一方法是每个接口有一个侦听套接字,并将套接字绑定到它们各自的接口。
首先,我的监听套接字是通过以下方式创建的:
s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
为了绑定套接字,我首先尝试的是接口名称,其中nic
a char*
是接口名称:
// Bind to a single interface
rc=setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, nic, strlen(nic));
if (rc != 0) { ... }
这根本没有效果 , 并且会静默失败。ASCII名称(例如eth0
)是否是传递给此调用的正确名称类型?为什么会无声地失败?根据man 7 socket
,“请注意,这仅适用于某些套接字类型,尤其是AF_INET套接字。数据包套接字不支持(在此使用普通的bind(8))。”
我不确定“数据包套接字”是什么意思,但这是一个AF_INET套接字。
所以我接下来尝试的是这个(基于bind vs SO_BINDTODEVICEsocket):
struct sockaddr_ll sock_address;
memset(&sock_address, 0, sizeof(sock_address));
sock_address.sll_family = PF_PACKET;
sock_address.sll_protocol = htons(ETH_P_ALL);
sock_address.sll_ifindex = if_nametoindex(nic);
rc=bind(s, (struct sockaddr*) &sock_address, sizeof(sock_address));
if (rc < 0) { ... }
那也失败了,但是这次出现了错误Cannotassignrequestedaddress
。我也尝试将系列更改为AF_INET,但失败并出现相同的错误。
剩下的一种选择是将套接字绑定到特定的IP地址。我可以查找接口地址并绑定到这些地址。不幸的是,这是一个不好的选择,因为由于DHCP和热插拔的以太网电缆,地址可以随时更改。
当涉及到广播和多播时,此选项可能也很糟糕。我担心绑定到特定地址将意味着我无法接收广播(广播到的地址不是我绑定的地址)。我实际上将在今晚晚些时候对此进行测试并更新此问题。
问题:
AF_PACKET
用SOCK_DGRAM
?我不明白所有的选择。谁能帮我解决这个问题?谢谢!
更新:
绑定到特定的IP地址无法正常工作。具体来说,我无法再接收广播数据包,这正是我要接收的数据包。
更新:
我尝试使用IP_PKTINFO
和recvmsg
获取有关正在接收的数据包的更多信息。我可以获得接收接口,接收接口地址,发送方的目标地址和发送方的地址。这是我收到一个广播数据包的报告的示例:
Got message from eth0
Peer address 192.168.115.11
Received from interface eth0
Receiving interface address 10.1.2.47
Desination address 10.1.2.47
真正奇怪的是eth0的地址是10.1.2.9,而ech1的地址是10.1.2.47。那么为什么eth0接收到eth1应该接收的数据包呢?这绝对是一个问题。
请注意,我启用了net.ipv4.conf.all.arp_filter,尽管我认为这仅适用于传出数据包。
我发现可以使用的解决方案如下。首先,我们必须更改ARP和RP设置。在/etc/sysctl.conf中,添加以下内容并重新启动(还有一个命令可以动态设置此内容):
net.ipv4.conf.default.arp_filter = 1
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.all.arp_filter = 1
net.ipv4.conf.all.rp_filter = 2
必须使用arp过滤器,以允许eth0的响应通过WAN路由。必须使用rp筛选器选项,才能将传入的数据包与传入的NIC严格关联(与弱模型相比,该模型将传入的数据包与与子网匹配的任何NIC关联起来)。EJP的评论使我迈出了关键的一步。
之后,SO_BINDTODEVICE开始工作。两个套接字中的每个套接字都绑定到其自己的NIC,因此我可以根据消息来自哪个NIC来判断消息来自哪个NIC。
s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
rc=setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, nic, IF_NAMESIZE);
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(LISTEN_PORT);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
rc=bind(s, (struct sockaddr *)&si_me, sizeof(si_me))
接下来,我想用源地址是原始请求来自的NIC的数据报来响应传入的数据报。答案是只查找该NIC的地址,然后将传出的套接字绑定到该地址(使用bind
)。
s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
get_nic_addr(nics, (struct sockaddr *)&sa)
sa.sin_port = 0;
rc = bind(s, (struct sockaddr *)&sa, sizeof(struct sockaddr));
sendto(s, ...);
int get_nic_addr(const char *nic, struct sockaddr *sa)
{
struct ifreq ifr;
int fd, r;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) return -1;
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, nic, IFNAMSIZ);
r = ioctl(fd, SIOCGIFADDR, &ifr);
if (r < 0) { ... }
close(fd);
*sa = *(struct sockaddr *)&ifr.ifr_addr;
return 0;
}
(也许每次都查找NIC地址似乎是一种浪费,但是当地址更改时,这是通过更多的代码来获得通知的方式,并且在不使用电池供电的系统上,这些事务每隔几秒钟发生一次。)
当我尝试通过局域网ping minecraft服务器时,文档会说: 我试图通过以下方式在python中实现这一点 这给了我一个 请帮助:(我不知道我的代码出了什么问题。 顺便说一句,发送数据包到那个端口是有效的,而假冒的服务器会出现在minecraft应用程序上。
问题内容: 我的应用程序在CentOS 5.5上运行。我正在使用原始套接字发送数据: 如何将此套接字绑定到特定的网络接口(例如eth1)? 问题答案: 第一行:设置变量 第二行:告诉程序绑定到哪个接口 第3-5行:获取接口名称的长度,并检查其大小是否太大。 六行:设置套接字的套接字选项,绑定到设备。 setsockopt原型: 此外,请确保您包括,和头文件
问题内容: 我目前正在使用 属性启动Java VM,以便可以通过JConsole连接到Java VM 进行管理和监视。不幸的是,它监听计算机上的所有接口(IP地址)。 在我们的环境中,通常情况下,一台机器上同时运行多个Java VM。尽管可以告诉JMX侦听不同的TCP端口(使用),但是最好让JMX使用标准的JMX端口并仅绑定到特定的IP地址(而不是所有IP地址)。 这将使查找通过JConsole连
问题内容: 这可能是一件非常简单的事情。我是python的新手,所以不要钉死我。 上面的命令给了我: 我唯一的进口是 问题答案: 如果您不理解错误消息,则表示您引用的是当时不可用的名称。您的代码段可能缺少导入语句。 出于可移植性的原因,套接字模块可能不提供SO_BINDTODEVICE。如果您完全确定自己在支持它的Linux上运行,请尝试用它的数字值替换它: 或对于python 3:
问题内容: 我正在编写代码以在两个Linux盒之间发送原始以太网帧。为了测试这一点,我只想获得一个简单的客户端发送和服务器接收。 我让客户端正确地制作了数据包(我可以使用数据包嗅探器看到它们)。 在服务器端,我像这样初始化套接字: 我用作ethertype的2字节常量在哪里,所以我听不到多余的网络流量。 当我将此套接字绑定到接口时,必须在socket_addr结构中再次将其传递给协议: 如果我像这
当我使用nc侦听端口时,它显示 但我找不到使用netstat/ss工具占用此端口的任务 ;什么也找不到 ;什么也找不到 这个端口被我的java程序占用,代码是: 它只显示侦听中的socks或从tcp_hashinfo建立的socks。但是tcp_hashinfo有三个结构 bhash可用于绑定。但不在/proc/net/tcp中导出。