Of course we cannot always share details about our work with customers, but nevertheless it is nice to show our technical achievements and share some solutions.
Sometimes you might want to quickly look up your current public IP address. Or you might need to monitor the public IP address of an application as it is relevant to the health of the application (see article PowerDNS master slave replication stopped working due to AWS Elastic IP mysteriously gone).
In such scenarios, public (and free) services such as ifconfig.co or icanhazip.com are great helpers. But as these services are free and open to everyone, they might receive a lot of traffic. A lot of traffic.
Even with some limits on connections per second, icanhazip is still poised to top 14.3TB of bandwidth this month according to vnstat.
- Major Hayden (icanhazip.com)
Not seldomly these free services also suffer various attacks, such as DDoS. If such a service is down and your application somehow relies on a frequent remote IP lookup, your own application might go down.
Of course you could always deploy your quick public IP lookup. In PHP you'd simply use a snippet like this:
<?php echo $_SERVER['REMOTE_ADDR']; ?>
In case your web server runs behind a reverse proxy, you might want to change this to the HTTP header which contains the forwarded remote ip address (mostly X-Forwarded-For or X-Real-IP):
<?php echo $_SERVER['HTTP_X_FORWARDED_FOR']; ?>
It's as easy as this. However ifconfig.co offers much more than just showing the client's IP address. It also allows json output for application parsing, adds GeoIP based information and more. To "copy" this into your own PHP code will need someone really motivated (or bored). But there's an easier way.
The whole website ifconfig.co including the backend service (written in Go) is actually available as echoip on GitHub. Even Docker images are available from Docker Hub. If you already have your own Container environment it's incredibly easy and fast to deploy your own ifconfig.co service! In this example we're using our Rancher 2 managed Kubernetes environment to deploy such a service.
The service (workload) was defined as a DaemonSet (one pod per node) and simply the Docker image name was entered: mpolden/echoip. If you're new to Docker images, this means download the latest "echoip" image from the public Docker Hub repository "mpolden".
After clicking on [Launch], it only took a couple of seconds and the service was deployed across all the nodes in that Kubernetes cluster. Now that the service is running, an Ingress rule needs to be added.
By default, echoip listens on the internal port tcp/8080. This means the Ingress rule with the public domain (here ifconfig.example.com) points to the workload using the internal IP 8080:
Now just point your public domain to the Ingress of that Kubernetes cluster and you're good to go!
When you launch a HTTP request to your public domain, you should be able to get your IP address as a response. However in a Kubernetes environment using Ingress for incoming http/https, the response most likely contains an internal IP:
$ curl ifconfig.example.com
Guess what? Yes, that's actually the IP address of the Ingress pod, forwarding the HTTP request to one of the echoip pods. To be able to return the "real" IP address from where the HTTP request originated, two requirements must be fulfilled:
When looking at the Dockerfile of echoip, the following entry point is used:
This means that echoip is launched without any parameters inside the pod; the default settings are applied in this case.
To tell echoip to use a specific HTTP header as remote IP, the -H parameter can be used. Simply adjust the entrypoint configuration when deploying the workload to use the X-Forwarded-For header. In Rancher 2 you can overwrite the entrypoint from a Dockerfile using the Entrypoint field:
/opt/echoip/echoip -H X-Forwarded-For
Note: The "Command" section might be hidden by default. Use "Show advanced options" when deploying or editing a workload.
After the echoip workload was redeployed with the new entrypoint, the HTTP request from remote now shows the correct public IP:
$ curl ifconfig.example.com
Of course in a production environment, a Kubernetes node should never be directly accessible by Internet. For security reasons a reverse proxy or load balancer should be placed in between the Ingress and public Internet. Such an architecture could look like this:
From a point of view of the echoip application it doesn't matter though whether or not there are additional "hops" in front of the Ingress. The only thing which needs to be considered is that the reverse proxy or load balancer forwards the client's IP address as X-Forwarded-For header. In AWS Elastic Load Balancers (ELB) this is already configured by default.
If you are looking for a managed and dedicated Kubernetes environment, managed by Rancher 2, with server location Switzerland, check out our Private Kubernetes Container Cloud Infrastructure offer at Infiniroot.