m.ac

Build a WHOIS compatibility server with Python and Nginx

409 words2 min read

#Background

ICANN's January 27, 2025 update made RDAP the definitive source for gTLD registration data, with legacy WHOIS services retired. For new registration data lookups, use RDAP.

The Registration Data Access Protocol (RDAP) is the successor to the traditional WHOIS protocol. It uses HTTPS and structured responses instead of unencrypted, loosely formatted text over port 43.

If you run registry or registrar infrastructure, move clients to RDAP rather than keeping a full WHOIS service around forever. We have already completed that migration for xTom GmbH (IANA ID 3968).

Old applications still query WHOIS on port 43, so this server keeps compatibility clients from failing silently. It accepts the connection and returns a plain message that points users to RDAP.


#1. Prerequisites

There are two straightforward ways to build this kind of WHOIS compatibility endpoint: Nginx stream alone, or a small Python service behind Nginx.

The commands below use sudo. If you prefer a root shell, run sudo -i first and drop sudo from the commands.

Install the required packages:

bash
sudo apt update
sudo apt install -y lsb-release ca-certificates apt-transport-https curl gnupg dpkg python3

Add the N.WTF repository, which provides an Nginx mainline build with the stream module enabled:

bash
curl -sS https://n.wtf/public.key | sudo gpg --dearmor -o /usr/share/keyrings/n.wtf.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/n.wtf.gpg] https://mirror-cdn.xtom.com/sb/nginx/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/n.wtf.list

Install Nginx:

bash
sudo apt install nginx-extras -y

#2. Build a WHOIS server with the Nginx stream module

The Nginx stream module can return a fixed message on port 43. Add this block to /etc/nginx/nginx.conf:

nginx
stream {
    # Define rate limiting zone
    limit_conn_zone $binary_remote_addr zone=whois_stream_conn:10m;

    # simple whois server
    server {
        listen 43;
        listen [::]:43;

        # Connection limits
        limit_conn whois_stream_conn 5;

        proxy_timeout 10s;

        # Return a message to the client
        return "NOTICE: In accordance with ICANN compliance policies, our whois server has been discontinued. Please use the RDAP protocol for all domain whois queries.\n\nFor more information, please visit:\n\nhttps://www.icann.org/en/announcements/details/icann-update-launching-rdap-sunsetting-whois-27-01-2025-en\nhttps://www.icann.org/resources/pages/global-amendment-2023-en\n\n";
    }
}

Test the configuration and reload Nginx:

bash
sudo nginx -t
sudo nginx -s reload

Some WHOIS clients do not like this version. A query may print:

plaintext
fgets: Connection reset by peer

The Nginx stream return approach writes the message and closes the TCP session immediately. That is enough for some clients, but others report fgets: Connection reset by peer instead of printing the text cleanly.

Using a tiny Python service gives us better control over reading the query, writing the response, and closing the connection.


#3. Build a WHOIS server with Python and Nginx

The Python script listens locally and returns a predefined message to each WHOIS client.

Clone the repository and copy whois.py to /opt/:

bash
git clone https://git.m.ac/showfom/whois-server
cd whois-server
sudo cp -r whois.py /opt

Copy the systemd service template to /etc/systemd/system/:

bash
sudo cp -r whois-server.service /etc/systemd/system/

Enable and start the service:

bash
sudo systemctl daemon-reload
sudo systemctl enable --now whois-server

Test the WHOIS service locally:

bash
whois anything -h 127.0.0.1:10043

It should return the configured message:

plaintext
NOTICE: In accordance with ICANN compliance policies, our whois server has been discontinued. Please use the RDAP protocol for all domain whois queries.

For more information, please visit:

https://www.icann.org/en/announcements/details/icann-update-launching-rdap-sunsetting-whois-27-01-2025-en
https://www.icann.org/resources/pages/global-amendment-2023-en

Now configure Nginx to proxy public port 43 traffic to the local Python service.

Add this block to /etc/nginx/nginx.conf:

nginx
stream {
    # Define rate limiting zone
    limit_conn_zone $binary_remote_addr zone=whois_stream_conn:10m;

    # whois server
    server {
        listen 43;
        listen [::]:43;

        # Connection limits
        limit_conn whois_stream_conn 5;

        # Forward requests to the local Python script service
        proxy_pass 127.0.0.1:10043;
        proxy_timeout 30s;
    }
}

Test the configuration and reload Nginx:

bash
sudo nginx -t
sudo nginx -s reload

Query the public WHOIS endpoint:

bash
whois anything -h localhost

You can also create a WHOIS hostname with A and AAAA records pointing to this server, then submit that hostname wherever a registry still asks for an official WHOIS server.

Build a WHOIS compatibility server with Python and Nginx
Author
Xiufeng Guo
Published
Apr 29, 2025
Last updated
May 18, 2025
License
Short link
ADShare it the short way.URL shortener, file and text sharing, link in bio. Run by yours truly.S.EE →
Share