Skip to content

Commit 1771f11

Browse files
committed
Initial version of real IPs post
Signed-off-by: Alex Ellis (OpenFaaS Ltd) <[email protected]>
1 parent b08f5a8 commit 1771f11

File tree

3 files changed

+153
-0
lines changed

3 files changed

+153
-0
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,14 @@ arch -arch x86_64 $GEM_HOME/bin/bundle install
121121
arch -arch x86_64 $GEM_HOME/bin/bundle exec jekyll serve
122122
```
123123

124+
## Running in Docker
125+
126+
If you have had some issues installing the various gems, then you can use Docker instead:
127+
128+
```bash
129+
docker-compose up
130+
```
131+
132+
Then access the site at http://127.0.0.1:4000
133+
134+
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
layout: post
3+
title: Get Real Client IPs with Ingress Nginx, Caddy or Traefik
4+
description: Whether you're running a reverse proxy directly on a host, or an Ingress Controller in Kubernetes, you can get the real client IP with inlets.
5+
author: Alex Ellis
6+
tags: load-balancer ingress-controller reverse-proxy proxy-protocol
7+
author_img: alex
8+
image: /images/2024-10-real-ips/background.png
9+
date: 2024-10-08
10+
---
11+
12+
When you're running a reverse proxy directly on a host, or an Ingress Controller in Kubernetes, you can get the real client IP with inlets.
13+
14+
The real client IP address is required for rate-limiting, effective logging, understanding where your users are coming from geographically, and to prevent abuse. Just bear in mind that if you choose to store these addresses within a database, or server logs, you may need to comply with data protection laws like GDPR.
15+
16+
We've covered how Proxy Protocol works before in the original post [Get Real Client IPs with K3s and Traefik](https://inlets.dev/blog/2022/09/02/real-client-ips-with-proxy-protocol.html), so that's a good refresher if you'd like to cover the fundamentals again.
17+
18+
In this post we'll focus on the configuration you need, so you can come back here and copy/paste it when you need it.
19+
20+
## The Inlets Setup
21+
22+
Deploy a host and install the `inlets-pro tcp server`, you can [do this manually](https://docs.inlets.dev/tutorial/manual-tcp-server/) or via cloud-init.
23+
24+
The [inletsctl tool](https://docs.inlets.dev/reference/inletsctl/) can create a host using a cloud provider's API, and pre-install the inlets-pro server for you, with a randomly generated authentication token, and will print out all the details at the end.
25+
26+
Whichever method you take, log into the host, and edit the systemd unit file for inlets-pro, find it via `sudo systemctl cat inlets-pro`.
27+
28+
Add `--proxy-protocol=v2` to the `ExecStart` line, if it's already present with an empty value, update it instead.
29+
30+
The v2 protocol is widely supported and more efficient than v1, since it sends text in a binary format, not in a human-readable format.
31+
32+
## Real IPs for Caddy
33+
34+
I've included this section for when you want to run a reverse proxy in a VM, container, or directly on your machine. The other examples are focused on running a reverse proxy in Kubernetes, called an Ingress Controller. For instance, you may be running OpenFaaS via [faasd CE](https://github.com/openfaas/faasd). In that case, Caddy is a quick way to get TLS termination for your OpenFaaS functions, and anything else you are running in your setup like Grafana.
35+
36+
The following settings are for when you run Caddy directly on your own machine, and use an inlets TCP tunnel server to expose it to the Internet, pointing ports 80 and 443 to your Caddy instance.
37+
38+
```
39+
{
40+
41+
42+
acme_ca https://acme-v02.api.letsencrypt.org/directory
43+
http_port 80
44+
https_port 443
45+
46+
servers {
47+
listener_wrappers {
48+
proxy_protocol {
49+
timeout 2s
50+
allow 0.0.0.0/0
51+
}
52+
tls
53+
}
54+
}
55+
}
56+
57+
orders.example.com {
58+
reverse_proxy 127.0.0.1:8080
59+
}
60+
61+
```
62+
63+
There are a number of extra settings over a basic Caddyfile for Let's Encrypt, but the main one we need is the `proxy_protocol` listener wrapper.
64+
65+
You'll see I've also included an upstream for `orders.example.com` which is a plain HTTP service running on port 8080. It will receive the real client IP from Caddy, and can read it from the `X-Real-IP` header.
66+
67+
68+
## Real IPs for ingress-nginx
69+
70+
The [ingress-nginx documentation site](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#use-proxy-protocol) explains the various settings that can be configured for an installation of ingress-nginx. One of those options is for Proxy Protocol. You don't need to set a version, just set it to `true` and either version will be accepted.
71+
72+
Edit the ConfigMap for ingress-nginx, when installed via arkade, it will be called `ingress-nginx-controller`, so:
73+
74+
```bash
75+
kubectl edit configmap ingress-nginx-controller
76+
```
77+
78+
Within the `data:` section, add:
79+
80+
```diff
81+
data:
82+
+ use-proxy-protocol: "true"
83+
```
84+
85+
There are some additional related headers, which you can customise:
86+
87+
```diff
88+
data:
89+
+ compute-full-forwarded-for: "true"
90+
+ enable-real-ip: "true"
91+
+ proxy-protocol-header-timeout: 1s
92+
+ set-real-ip-from: 0.0.0.0/0
93+
+ use-forwarded-headers: "true"
94+
```
95+
96+
Once updated, the controller will reload its settings and will only accept requests which have a Proxy Protocol header. If you send a request without the header, it will be rejected, so it must only be accessed via the inlets tunnel.
97+
98+
## Real IPs for Traefik
99+
100+
This section was taken [from the original blog post](https://inlets.dev/blog/2022/09/02/real-client-ips-with-proxy-protocol.html). You can refer there for more details.
101+
102+
[Traefik](https://traefik.io) ships with [K3s](https://k3s.io) by default, and is installed into the `kube-system` namespace.
103+
104+
When I create k3s clusters with [k3sup](https://k3sup.dev), I tend to turn off Traefik in order to add ingress-nginx which I find to be simpler, broadly used in production setups, and easier to operate. I just run: `k3sup install --no-extras` to make sure Traefik won't be installed.
105+
106+
If you want to use Traefik, you can do so by editing the deployment:
107+
108+
```bash
109+
kubectl -n kube-system edit deployment traefik
110+
```
111+
112+
Then add the following flags:
113+
114+
```diff
115+
spec:
116+
containers:
117+
- args:
118+
+ - --entryPoints.web.proxyProtocol.insecure=true
119+
+ - --entryPoints.web.proxyProtocol.trustedIPs=0.0.0.0/24
120+
+ - --entryPoints.websecure.proxyProtocol.insecure=true
121+
+ - --entrypoints.websecure.http.tls
122+
+ - --entrypoints.web.address=:8000/tcp
123+
+ - --entrypoints.websecure.address=:8443/tcp
124+
```
125+
126+
I also add `- --accesslog=true` to help find any potential issues with the configuration.
127+
128+
If Traefik doesn't detect the settings immediately, you can restart it with `kubectl rollout restart -n kube-system deployment traefik`.
129+
130+
If you wish to swap Traefik for ingress-nginx, you can run:
131+
132+
```bash
133+
kubectl delete -n kube-system deployment traefik
134+
kubectl delete -n kube-system service traefik
135+
```
136+
137+
## Wrapping up
138+
139+
I wanted this article to be a short and sweet reference for you, on how to configure the most popular reverse proxies to accept the Proxy Protocol header, so that your applications can get the real client IP.
140+
141+
If you have any questions or suggestions, please feel free to reach out. Whenever you sign up for a subscription for inlets, you'll get an invite to our Discord community. If you signed up some time, ago reach out via the form on the website and we'll get you an invite.
142+
47.2 KB
Loading

0 commit comments

Comments
 (0)