ルーターで「トラフィックを監視する」種類のアプリケーションを開発しています。この機能を使用して、TPROXY
DNS パケットをインターセプトし、ポートでリッスンしているアプリケーション サーバーに送信します。処理後、TTL を変更した後、パケットを実際の宛先 (dnsmasq) に転送します。
JFYI、ポート 2345 でリッスンしているアプリケーション サーバーに DNS 応答パケットを転送する TPROXY に対する私のファイアウォール ルールは次のようになります。
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 を返します。ここで何が欠けていますか?