AIS Relay Server Usage Guide

This document describes how to consume AIS data from the AIS Relay Server. The relay provides authenticated access to raw AIS NMEA messages and database snapshots. All external AIS feeds are secured using TLS and exposed locally via a TCP relay.

1. Secure AIS Feed via Stunnel (Client Setup)

The upstream AIS data source requires a TLS-encrypted connection. To simplify client access, stunnel is used to terminate TLS locally and expose the AIS stream as a plain TCP socket.

Once stunnel is running, AIS data will be available locally on:

127.0.0.1:5000

Example stunnel Client Configuration

client = yes
foreground = yes
debug = info

[secure-service-client]
accept = 127.0.0.1:5000
connect = ais-data-relay.streams.sunet.se:5000
checkHost = ais-data-relay.streams.sunet.se
cert = ./client.crt
key = ./client.key
CAfile = ./ca.crt
verifyChain = yes
verifyPeer = no

Required files in the stunnel directory:

Start the stunnel client using:

sudo stunnel client-stunnel.conf

All applications should connect only to the local TCP port. They do not need to handle TLS directly.

2. TCP Relay (Port 5000)

The TCP relay provides raw AIS NMEA sentences over a plain TCP connection. The relay maintains a single connection to the upstream AIS source while allowing multiple authenticated clients to connect simultaneously.

Python Async TCP Client Example

import asyncio

async def tcp_client(USERNAME="admin", PASSWORD="1234"):
    reader, writer = await asyncio.open_connection("localhost", 5000)

    prompt = await reader.readline()
    print(prompt.decode().strip())
    writer.write((USERNAME + "\n").encode())
    await writer.drain()

    prompt = await reader.readline()
    print(prompt.decode().strip())
    writer.write((PASSWORD + "\n").encode())
    await writer.drain()

    result = await reader.readline()
    print(result.decode().strip())

    try:
        while True:
            line = await reader.readline()
            if not line:
                break
            print(line.decode().strip())
    except KeyboardInterrupt:
        writer.close()
        await writer.wait_closed()

asyncio.run(tcp_client())

3. Database Snapshot (HTTP)

The relay maintains a local SQLite database containing the latest AIS state. A snapshot of this database can be downloaded via an authenticated HTTP endpoint.

Python Requests Example

import requests
from requests.auth import HTTPBasicAuth

url = "http://localhost:8000/db/snapshot"
response = requests.get(url, auth=HTTPBasicAuth("admin", "1234"))

with open("ais_snapshot.db", "wb") as f:
    f.write(response.content)

4. Quick curl Example

curl -u admin:1234 http://localhost:8000/db/snapshot -o ais_snapshot.db

Authentication Notes:
• TCP clients authenticate using a username/password prompt.
• HTTP and WebSocket clients must use HTTP Basic Authentication headers.