Noo you can't just enter my website when I restricted the access in my Apache!"
IP machine goes brr
- Apache2 web server with a running virtual host
- Cloudflare account linked to your webserver
A month ago I put my website behind Cloudflare's CDN with the intention to get my way around the service and who knows.. even speed up my website a bit. However, I did not want people to be able to see my website under development. The first thing that came to my mind was to put a "Coming Soon" page but I instantly figured this is a little stupid way to 'restrict' somebody to my content as they can still browse around URLs. What did I decide to do? I decided to only allow certain IPs on the Apache level. What happened? I could not do it. Then with some research, I got to understand why it did not work and what is an X-Forwarded-For header, and how to use it to suit my needs.
I have a website running on Apache webserver behind Cloudflare's CDN. I need to restrict access to my website on Apache level to only be accessible with the IP x.x.x.x
What is X-Forwarded-For header?
"The X-Forwarded-For header is a standard header for identifying the originating IP address." Meaning? This means that if my IP is x.x.x.x and I try to connect to the website example.com which is behind a Cloudflare CDN, then I am connecting to Cloudflare, only which then handles my connection to the website. Cloudflare is connecting to the example.com's server and therefore, you could say, it has the role of a reverse proxy. If you try to ping my website you will not get my IP. You will get CloudFlare's IP.
With the X-Forwarded-For header, the webserver is able to get the originating IP of the connected user.
Denying the IP without X-Forwarded-For?
The answer to this is simple - you will try blocking an IP but that IP does not have anything to do with your webserver. If the IP has already connected to CloudFlare, then the Cloudflare IP is connecting to your website -> the content is still available to the user.
Example: Your IP: A.A.A.A My Server IP: B.B.B.B CloudFlare IP: C.C.C.C
You(A.A.A.A) enter 47ontech.com(B.B.B.B) -> You(A.A.A.A) connect to CloudFlare(C.C.C.C) -> Cloudflare(C.C.C.C) connects you to my server(B.B.B.B) -> You(A.A.A.A) do not connect to me(B.B.B.B). You(A.A.A.A) connect to CloudFlare(C.C.C.C), which connects to me(B.B.B.B) -> You see my website -> not what we need :(
Denying the IP WITH X-Forwarded-For!
Let's get straight to the point and see what would happen if you deny an IP with X-Forwarded-For, with an example:
Example: Your IP: A.A.A.A My Server IP: B.B.B.B Cloudflare IP: C.C.C.C
You(A.A.A.A) enter asciinaut.sh (B.B.B.B) -> You(A.A.A.A) connect to Cloudflare(C.C.C.C) -> Cloudflare(C.C.C.C) connects you to my server(B.B.B.B) -> You(A.A.A.A) are thrown away as your IP is stored in the packet header in the X-Forwarded-For variable. Meaning? My apache saw your real IP and it did not allow you to pass -> There is no content served other than 403 forbidden.
Cool, you got the point! Now you just need the final ingredient - the Apache block. Let me get it out for you real quick:
<Directory /var/www/path/to/your/project> SetEnvIF X-Forwarded-For "x.x.x.x" AllowIP Options Indexes FollowSymLinks AllowOverride All <RequireAny> Require env AllowIP </RequireAny> </Directory>
And that's pretty much it! You include this block to your Apache config after your /VirtualHost and you are ready to go!
Some side note - If you want to check what your connection consists of, create a file examplefile.php in your website directory and add the following lines:
Now browse to this file and you will see a huge block of information. Here you can see what your connection consists of. And now if you want to check if something is working, for example, the X-Forwarded-For header - just CTRL+F and type it in the search bar.
In this post, you learned how to restrict access to only certain IPs when you are making use of Cloudflare(or any CDN really..). You learned what the X-Forwarded-For header is. And you learned a small bit of how content delivery networks work. I hope this helped you and if you ever want to start a conversation with me or just want to contact me - feel free to drop me a message on my Twitter!
Best of luck with your projects and don't forget to have fun in the terminal!