Python 3 WireGuard Health Check

In the High Availability WireGuard on AWS article, I included the source code for a simple service that you can use as a WireGuard health check for AWS ELB (Amazon Web Services Elastic Load Balancing). That code is intended to be run on Amazon Linux 2 (a derivative of Red Hat Enterprise Linux 7), which comes with an older version of the Python programing language, Python 2.

Newer Linux distributions come with Python 3, however. Following is the Python 3 version of the health-check code:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from http.server import HTTPServer, BaseHTTPRequestHandler
from optparse import OptionParser
from os import popen

class HealthCheck(BaseHTTPRequestHandler):

    def do_GET(self):
        if check(self.server.device):
            self.send_response(200)
            self.send_header("Content-Type", "text/plain")
            self.end_headers()
            self.wfile.write(b"healthy\n")
        else:
            self.send_error(404)

    def do_HEAD(self):
        self.do_GET()

def check(device):
    return popen("ip link show %s up " % device).read() != ""

def test(device):
    if check(device):
        print("%s up" % device)
    else:
        print("%s down" % device)

def main(port, device):
    server = HTTPServer(('', port), HealthCheck)
    server.device = device
    server.serve_forever()

def opts():
    parser = OptionParser(
            description="HTTP server that sends 204 response when device is up.")
    parser.add_option("-d", "--device", dest="device", default="wg0",
            help="device name to check (default wg0)")
    parser.add_option("-p", "--port", dest="port", default=8080, type="int",
            help="port on which to listen (default 8080)")
    parser.add_option("-t", "--test", action="store_true", dest="test", default=False,
            help="show status and exit")
    return parser.parse_args()[0]

if __name__ == "__main__":
    options = opts()
    if options.test:
        test(options.device)
    else:
        main(options.port, options.device)

It runs a simple HTTP server that responds with a 200 (OK) status code when the configured WireGuard interface is up, and a 404 (Not Found) status code when it is down.

You can configure the interface it checks via the --device flag, and the port on which it listens via the --port flag. For example, to check the wg1 interface, and listen on the port 8000, run it like this:

$ ./wg-health-check.py --device=wg1 --port=8000

The defaults are to check the wg0 interface, and listen on port 8080.

To run it as a service on system startup, use the same systemd unit file used by the Python 2 version of this code from the Set Up WireGuard Server Health Check section of the original article.