I believe I am dealing with a routing issue on my system (which is a default Ubuntu 22 installation) but I really can’t understand how to approach the debugging of said problem.
By following the Kernel’s Transparent Proxy tutorial, I’m trying to implement a transparent proxy for all the outbound UDP traffic with destination port being 53 (that is, I’m trying to filter all the DNS requests on my system).
After many tutorials online, here’s the setup that I think should work (but doesn’t actually):
# iptables -t mangle -N DIVERT
# iptables -t mangle -A PREROUTING -p udp -m socket -j DIVERT
# iptables -t mangle -A DIVERT -j MARK --set-mark 1
# iptables -t mangle -A DIVERT -j ACCEPT
# ip rule add fwmark 1 lookup 100
# ip route add local 0.0.0.0/0 dev lo table 100
# iptables -t mangle -A PREROUTING -p udp --dport 53 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 5354
The C code for the actual UDP socket that waits for incoming traffic:
void intercept()
{
int fd;
ssize_t bytes_received_len;
char buffer[BUFFER_SIZE];
struct sockaddr_in inbound_addr, forward_server_addr;
socklen_t addr_len = sizeof(inbound_addr);
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("inbound socket creation failed");
exit(EXIT_FAILURE);
}
int val = 1;
setsockopt(fd, SOL_IP, IP_TRANSPARENT, &val, sizeof(val));
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(5354);
bind(fd, (struct sockaddr *)&addr, sizeof(addr));
for (;;)
{
printf("waiting on port 5354n");
bytes_received_len = recvfrom(fd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&inbound_addr, &addr_len);
printf("received %zd bytesn", bytes_received_len);
if (bytes_received_len == 0)
{
continue;
}
}
}
All the error handling is skipped for clarity.
As you can see from the iptables commands, I’m trying to outbound traffic to port 53 into my local proxy at 127.0.0.1: 5354. I never actually receive anything useful from recvfrom
even if I actuall DNS requests on my system and they work, but they seem to bypass the proxy completely.
Am I missing anything super obvious?
I did look into all these articles:
- Above mentioned kernel tutorial
- This question: https://stackoverflow.com/questions/42738588/ip-transparent-usage
- Even if it’s about Rust, it was still useful: https://serverfault.com/questions/1143600/tproxy-is-not-redirecting-all-traffic-to-a-specified-port
- go-tproxy: https://github.com/KatelynHaworth/go-tproxy
Any pointer would be super helpful. It really just feels like I’m missing something really obvious.