Cloudflare blocking using iptables not quite working

Hi folks,

As my username suggests I’m not a fan of the Cloudflare systems and services.

I’ve setup a Transparent Proxy to direct all the traffic over Tor but if Cloudflare is the destination I simply do not want to communicate to it at all and want to know the moment any app tries to send data to it by checking the journal every second with:
journalctl -k --since "1 second ago"

and calling…
notify-send

with the offending event.

I know the Torification and logging is working from iptables, the only thing that has me stumped is that IPTables is not jumping to the LOGGING_ CLOUDFLARE chain, using the below iptables rules:

#  Following rules based on Archlinux Transparent Torification
#    https://wiki.archlinux.org/title/Tor#Transparent_Torification
#    with some extra sauce while mapping to a trap (127.1.66.60) all
#    the Cloudflare traffic.

#  Where is says <MY_TOR_UID_HERE> below is actually a number that
#   corresponds to Tor's UID

*nat

:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:CLOUDFLARE - [0:0]
:LOGGING_CLOUDFLARE - [0:0]

-A PREROUTING -m state --state RELATED,ESTABLISHED -j ACCEPT
#    Tried putting the below above but the above rule
-A PREROUTING -j CLOUDFLARE
-A PREROUTING ! -i lo -p udp -m udp --dport 53 -j REDIRECT --to-ports 5353
-A PREROUTING ! -i lo -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j REDIRECT --to-ports 9040

-A OUTPUT -o lo -j RETURN
-A OUTPUT -d 192.168.0.0/16 -j RETURN
-A OUTPUT -m owner --uid-owner <MY_TOR_UID_HERE> -j RETURN
-A OUTPUT -p udp -m udp --dport 53 -j REDIRECT --to-ports 5353
-A OUTPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j REDIRECT --to-ports 9040

#     These are published from Cloudflare's own website at
#       www.cloudflare.com/ips-v4
-A CLOUDFLARE -d 1.0.0.0/24 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 1.1.1.0/24 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 173.245.48.0/20 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 103.22.200.0/22 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 103.31.4.0/22 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 141.101.64.0/18 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 108.162.192.0/18 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 190.93.240.0/20 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 188.114.96.0/20 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 197.234.240.0/22 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 198.41.128.0/17 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 162.158.0.0/15 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 104.16.0.0/13 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 104.24.0.0/14 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 172.64.0.0/13 -j LOGGING_CLOUDFLARE
-A CLOUDFLARE -d 131.0.72.0/22 -j LOGGING_CLOUDFLARE

#   I'm logging the UID of the app so I can pinpoint 
#    what app might be using cloudflare
-A LOGGING_CLOUDFLARE -m limit --limit 1/sec --limit-burst 2 -j LOG --log-prefix "Cloudflare outgoing blocked: " --log-level 0 --log-uid
-A LOGGING_CLOUDFLARE -j DNAT --to-destination 127.1.66.60

COMMIT


*filter

:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]

-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -j REJECT --reject-with icmp-proto-unreachable


-A OUTPUT -o lo -p icmp -m state --state RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED -j ACCEPT
-A OUTPUT -m state --state INVALID -j REJECT --reject-with icmp-port-unreachable
#    The below is the rule that should reject cloudflare (btw I tried 
#     putting it above the three commands above)
-A OUTPUT -d 127.1.66.60/32 -j REJECT --reject-with icmp-port-unreachable
-A OUTPUT -d 127.0.0.0/8 -j ACCEPT
-A OUTPUT -d 192.168.0.0/16 -j ACCEPT
-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -m owner --uid-owner <MY_TOR_UID_HERE> -j ACCEPT
-A OUTPUT -j REJECT --reject-with icmp-port-unreachable

COMMIT

I must admit I’m not really an expert with iptables.

I did try:

sudo sysctl net.ipv4.ip_forward=1

Nope. EDIT: The request appears to go through Tor :frowning:

Pretty stumped right now.

My guess; you are jumping to CLOUDFLARE chain from PREROUTING, which are incoming packets. And in CLOUDFLARE chain you have rules with -d aka destination. Destination in prerouting are your IPs, whichever they are.
So either you want -s aka source ip addresses, or you need to jump to CLOUDFLARE chain from POSTROUTING (just looking at logic of packet flow, so you have to figure out what is actually needed for your case)

1 Like

Thank you kind person!!

We now understand that it is most likely the OUTPUT chain (in the --table nat) that we need to use.

The really funny thing is I always find the thing I need a day after I needed it. So tomorrow, I predict that a diagram will appear before me showing the movement of packets and that PREROUTING is for packets coming in.

Hahaha

Thanks. :slight_smile:

There is plenty of diagrams - just google ‘iptables packet flow’. FYI: OUTPUT (and INPUT) chains are only for packets originating and destined for machine you are setting these rules on. For everything else there is FORWARD. And before/after all these 3 chains there are all the other PREROUTING/POSTROUTING chains.

Edit: Another nitpick - and why you should study packet flow - you have -A PREROUTING -m state --state RELATED,ESTABLISHED -j ACCEPT in -t nat and then -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT in -t filter. This last rule shouldn’t get any packets, because all are already accepted in PREROUTING chain. However, I’m not 100% sure they act the same. I think -j ACCEPT in NAT table is just used to skip doing any NAT on the packet and that connection.

I was inspired to finally bite-the-bullet and do Transparent Tor proxying and Cloudflare warning, the above works with some minor adjustments to target the OUTPUT chain. Will post later.

It should be noted that the Archlinux page above says to add some lines to the torrc, so I did that:

sudo cp /etc/tor/torrc /etc/tor/torrc_ORIGINAL   # Copy file for 
                                                 #  easy restore.  

sudo bash << EOF
echo "## See Transparent Torification at https://wiki.archlinux.org/title/Tor#Transparent_Torification
## 
## After changing this file you need to restart Tor with:
##  sudo systemctl restart tor
SOCKSPort 9050
DNSPort 5353
TransPort 9040
" >> /etc/tor/torrc
EOF

I ran into a bizarre issue. Maybe you have an idea on how to solve @zbe, basically I was recording the traffic and later discovered that my PC opened a connection to gitlab.[OMITTED].org and although my SYN (connection) request appears to have gone through Tor the server was connecting back with me over the clearnet! It pushed megabytes to me over clearnet and I was ACK’ing (acknowledging the packets) over Tor!! When the file was finished downloading the connection was promptly closed, but I don’t know what the file was. Is there anything that is designed to talk to a host and that provides the clients IP address? I think I had Pamac open at the time a was browsing packages. I have auto-updates turned off.

I’m just wondering how this happened!

It seems like a massive leak. I’m going to try to work out a way to fix but if someone can point me/us in the right direction that would be good. Maybe clearnet connections that are not being returned through Tor should be logged and dropped?

Honestly, I would have to read about how “transparent tor” works, because I never tried setting up anything like that, but:

this sounds impossible to me. I don’t see a way how the server will know your IP if SYN packet uses TOR, unless you are missing something in configuration or with capturing packets. I might be missing something too though.

All very interesting. I’m actually not finished with the above. Some minor bugs, and some cloudflare sites/assets are still being fetched :frowning:

Btw, what’s happening with the gitlab.torproject.org pages? Is it just us or do pages like this (onion here) no longer load, EVEN WITH JAVASCRIPT SWITCHED ON.

Weird.

Both load fine for me.