I have some simple scripts that require the system to discover what its public IP address is so that when it changes, those scripts can update DNS accordingly.

I went for a really simple, but not-so-secure solution: Install php-fpm and have it print $_SERVER[‘X-FORWARDED-FOR’] back.

This isn’t great and PHP has a lot of security problems.

httpd and slowcgi

OpenBSD base comes with a great web server: httpd(8) and a way to execute common gateway interface (CGI) programs: slowcgi(8).

This is a snippet from httpd.conf to handle the output:

location "/example" {
        root "/cgi-bin"
        fastcgi
}

We’ll assume you have httpd already set up and enabled.

Ensure slowcgi is enabled and started:

doas rcctl enable slowcgi
doas rcctl start slowcgi

The source code

Here’s our example.c script that will output the remote IP address. We are using pledge(2) to only allow stdio.

/*
 * Very simple CGI program to output the IP address you're coming from
 */

#include <err.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

int
main(void)
{
	if (pledge("stdio", NULL) == -1)
		err(EXIT_FAILURE, NULL);

	const char *remote_ip;
	remote_ip = getenv("HTTP_X_FORWARDED_FOR");
	if (remote_ip == NULL)
		err(EXIT_FAILURE, NULL);

	puts("Status: 200 OK\r");
	puts("Content-Type: text/html\r");
	puts("\r");
	printf("%s", remote_ip);
	return(EXIT_SUCCESS);
}

Here’s the Makefile I wrote to compile and install it:

PREFIX?=/var/www

CFLAGS  += -static -g -W -Wall -Wextra

example: example.c
        ${CC} ${CFLAGS} example.c -o $@

all: example

clean:
        rm example

install: example
        install -o www -g www -m 500 example ${PREFIX}/cgi-bin/example

Once you run make and doas make install it will install it to the /var/www chroot into the /cgi-bin directory with secure permissions and then if you go to your web server to /example you should see your remote IP address provided the server is on the internet and not in your internal network.