skip to Main Content

I have a webserver running running with Apache on Ubuntu behind Cloudflare. I want to block a user using the iptables of the webserver. Here I want to implement to string match feature of iptables and drop the connection. Here is my rule which does not work:

iptables -I INPUT -m string --string "x-forwarded-for: 216.244.66.205" --algo bm --to 65535 -j DROP

After adding this rule the client is still able to hit the server.

I know Cloudflare’s specific header for client IP that is cf-connecting-ip. I am able to block the client with this. Here is the rule which works fine:

iptables -I INPUT -m string --string "cf-connecting-ip: 216.244.66.205" --algo bm --to 65535 -j DROP

The traffic from Cloudflare to the Web server is HTTP (port 80).

I have a load-balancer (haproxy) and some of the domains are running through this instead of Cloudflare. That is why I want to use XFF because cf-connecting-ip is specific to Cloudflare and XFF is supported by both.

I can see Cloudflare is properly attaching both cf-connecting-ip and XFF headers. Here is the output of tcpdump among multiple requests:

tcpdump -A -s 65535 'tcp port 80' | grep 216.244.66.205
x-forwarded-for: 216.244.66.205
cf-connecting-ip: 216.244.66.205
x-forwarded-for: 216.244.66.205
cf-connecting-ip: 216.244.66.205
x-forwarded-for: 216.244.66.205
cf-connecting-ip: 216.244.66.205
x-forwarded-for: 216.244.66.205
cf-connecting-ip: 216.244.66.205

Somehow the iptables are able to detect the string cf-connecting-ip but not x-forwarded-for.

Any help would be appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    Answering own question in the hope it can help someone.

    The issue was due to the differences in CASE of the letters. The server was passing the letters in different which was not matching the one provided.

    I just needed to add an extra option that is --icase which ignores the case (case-insensitive match).

    Now the command is:

    iptables -I INPUT -m string --string "x-forwarded-for: 216.244.66.205" --algo bm --to 65535 --icase -j DROP
    

  2. HTTP headers are at the Application Layer, while IPTables works lower down in the TCP/IP stack. The data you are looking to filter based on is not visible to IPTables.

    For websites behind Cloudflare you should configure IPTables to only allow Cloudflare IP addresses through, and use the Cloudflare Firewall to block the client IP addresses.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search