我正在路由器上开发一种“监控流量”的应用程序,我使用该TPROXY
功能拦截 DNS 数据包并将其发送到侦听端口的应用程序服务器。处理完后,我修改了 TTL 后,将数据包转发到了实际的目的地(即 dnsmasq)。
JFYI,我的 TPROXY 防火墙规则将 DNS 响应数据包转发到我在端口 2345 上侦听的应用程序服务器,如下所示:
iptables -t mangle -A PREROUTING -i <WAN-INTERFACE> -p udp --sport 53 -j TPROXY --tproxy-mark 0x3 --on-port 2345
在我的应用程序服务器上,没有错误检查:
sock_fd = socket(AF_INET, SOCK_DGRAM, 0 );
setsockopt(socket_fd, SOL_IP, IP_PKTINFO, &enabled, sizeof(int));
setsockopt(socket_fd, SOL_IP, IP_TRANSPARENT, &enabled, sizeof(int));
setsockopt(socket_fd, SOL_IP, IP_RECVORIGDSTADDR, &enabled, sizeof(int));
setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &enabled, sizeof(int));
/* client_addr points to the source IP (i.e. upstream DNS server's IP) */
bind(sock_fd, (const struct sockaddr *)client_addr, sizeof(struct sockaddr));
/* dst_addr points to the router IP on the WAN interface */
sendto(sock_fd, dns_packet_buffer, data_len, 0,
(const struct sockaddr *)dst_addr, sizeof(struct sockaddr));
这样sendto
就成功了,即没有错误!!!但是,dnsmasq 没有收到数据!更准确地说,dnsmasq 正在等待数据的 fd 并没有“准备好”。
在 dnsmasq 代码中,里面check_dns_listeners
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
if (FD_ISSET(serverfdp->fd, set))
reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
FD_ISSET()
回报false
。_ 如果我不拦截 DNS 响应流,则FD_ISSET()
返回 true。我在这里想念什么?