Skip to content

Instantly share code, notes, and snippets.

@rgerganov
Last active May 21, 2023 19:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rgerganov/2a026d6dbc9bb9493082d2012bb1f49e to your computer and use it in GitHub Desktop.
Save rgerganov/2a026d6dbc9bb9493082d2012bb1f49e to your computer and use it in GitHub Desktop.
TH100 Wireguard HOWTO

Connecting TH-100 STBs to Wireguard VPN server

This guide shows how to connect TH-100 STBs to a Wireguard VPN server. On the server side you need a Linux box with Wireguard installed. For Debian/Ubuntu simply run:

$ sudo apt install wireguard
$ sudo sysctl -w net.ipv4.ip_forward=1

Your TH-100 STBs needs to run firmware version 286 or later.

Configuring the server

  1. Generate private key for the server:
$ wg genkey
CIVLquqtzkI2uZCKj2DEu2zqxp1kalvyO7KHojO1EmE=

The private key goes into /etc/wireguard/wg0.conf on the server.

  1. Generate the corresponding public key:
$ echo -n 'CIVLquqtzkI2uZCKj2DEu2zqxp1kalvyO7KHojO1EmE=' | wg pubkey
oh4Mqs83cq6zvh0uZ1VLmocXp5v/IjB52C9Z6HC0BwU=

The public key needs to be configured on each TH-100 which will connect to the server (see below).

Let's say that you want to connect two STBs with MACs d0:9f:d9:a0:20:ea and d0:9f:d9:a0:20:a6. You can obtain the public key of TH-100 by using its MAC address like this:

$ curl https://stb.xakcop.com/pubkey/d0:9f:d9:a0:20:ea
SKTXhheT0P6aOWPLhcHdrcr2DheVPsAEkX+7WKiL23o=
$ curl https://stb.xakcop.com/pubkey/d0:9f:d9:a0:20:a6
gDIVnYb5ca4TpOKI3pPT3UuhpHWGXASSsoOD34i4hx8=

Now put the following into /etc/wireguard/wg0.conf

[Interface]
# This is the IP address of the server, it needs to be in the 10.0.0.0/8 network
Address = 10.0.0.1/8
# The UDP port used for Wireguard
ListenPort = 51820
# The server private key from above
PrivateKey = CIVLquqtzkI2uZCKj2DEu2zqxp1kalvyO7KHojO1EmE=

# substitute eth0 in the following lines to match the Internet-facing interface
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# This is the public key for TH-100 with MAC d0:9f:d9:a0:20:ea
PublicKey = SKTXhheT0P6aOWPLhcHdrcr2DheVPsAEkX+7WKiL23o=
# The IP of each TH-100 is "10.x.y.z" where x.y.z are the last 3 octets from the MAC address. The net mask should be always /32
AllowedIPs = 10.160.32.234/32

[Peer]
# This is the public key for TH-100 with MAC d0:9f:d9:a0:20:a6
PublicKey = gDIVnYb5ca4TpOKI3pPT3UuhpHWGXASSsoOD34i4hx8=
# The IP of each TH-100 is "10.x.y.z" where x.y.z are the last 3 octets from the MAC address. The net mask should be always /32
AllowedIPs = 10.160.32.166/32

You can start the server with:

sudo wg-quick up wg0

and bring it down with:

sudo wg-quick down wg0

Configuring TH-100

Let's say that the public IP of your Wireguard server is 163.172.161.0. Create th100.ini file with following content:

[Wireguard]
Enable=1
Endpoint=163.172.161.0:51820
ServerKey=oh4Mqs83cq6zvh0uZ1VLmocXp5v/IjB52C9Z6HC0BwU=

Please note that you must use an IP address for the server, hostnames don't work. Put this file on a flashdrive and then boot each TH-100 with it. When booted, it should connect to your VPN and route all traffic through it.

Automation

The creation of config files can be automated with the th100-wg.py script. Save all TH-100 MAC addresses into a file (e.g. macs.txt):

$ cat macs.txt
d0:9f:d9:a0:20:a6
d0:9f:d9:a0:20:a7
d0:9f:d9:a0:20:a8
d0:9f:d9:a0:20:a9

Then run the script like this:

$ ./th100-wg.py macs.txt 163.172.161.0:51820
Server config saved to wg0.conf
TH-100 config saved to th100.ini
#!/usr/bin/env python3
from subprocess import Popen, PIPE
import urllib.request
import socket
import sys
import re
template = """[Interface]
# This is the IP address of the server, it needs to be in the 10.0.0.0/8 network
Address = 10.0.0.1/8
# The UDP port used for Wireguard
ListenPort = 51820
# The server private key from above
PrivateKey = {}
# substitute eth0 in the following lines to match the Internet-facing interface
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
"""
peer_template = """[Peer]
# This is the public key for TH-100 with MAC {}
PublicKey = {}
# The IP of each TH-100 is "10.x.y.z" where x.y.z are the last 3 octets from the MAC address. The net mask should be always /32
AllowedIPs = {}
"""
th100ini_template = """[Wireguard]
Enable=1
Endpoint={}
ServerKey={}
"""
def genkeys():
process = Popen(["wg", "genkey"], stdout=PIPE)
(privout, err) = process.communicate()
exit_code = process.wait()
if exit_code != 0:
raise Exception("Error generating private key")
privkey = privout.decode('ascii').strip()
process = Popen(["wg", "pubkey"], stdin=PIPE, stdout=PIPE)
(pubout, err) = process.communicate(privout)
exit_code = process.wait()
if exit_code != 0:
raise Exception("Error generating public key")
pubkey = pubout.decode('ascii').strip()
return privkey, pubkey
def validate_endpoint(endpoint):
ip, port = endpoint.split(':')
socket.inet_aton(ip)
pnum = int(port)
if pnum<=0 or pnum>=65535:
raise Exception("Incorrect port")
def fetch_pubkey(mac):
with urllib.request.urlopen('https://stb.xakcop.com/pubkey/{}'.format(mac)) as response:
return response.read().decode('ascii')
def generate_server_conf(privkey, macs):
conf = template.format(privkey)
mac_regx = re.compile(r'^[0-9A-F]{2}\:[0-9A-F]{2}\:[0-9A-F]{2}\:[0-9A-F]{2}\:[0-9A-F]{2}\:[0-9A-F]{2}$', re.IGNORECASE)
for mac in macs:
if not mac_regx.match(mac):
print("Skipping incorrect MAC: {}".format(mac))
continue
octets = mac.split(':')
ip = "10.{}.{}.{}/32".format(int(octets[3], 16), int(octets[4], 16), int(octets[5], 16))
pubkey = fetch_pubkey(mac)
peer = peer_template.format(mac, pubkey, ip)
conf += peer
with open("wg0.conf", "w") as f:
f.write(conf)
print("Server config saved to wg0.conf")
def generate_th100ini(pubkey, endpoint):
conf = th100ini_template.format(endpoint, pubkey)
with open("th100.ini", "w") as f:
f.write(conf)
print("TH-100 config saved to th100.ini")
if __name__ == '__main__':
if len(sys.argv) < 3:
print("Usage: {} <file-with-macs> <endpoint>".format(sys.argv[0]))
sys.exit(1)
macs_file = sys.argv[1]
privkey, pubkey = genkeys()
with open(sys.argv[1], "r") as f:
macs = f.read().split()
endpoint = sys.argv[2]
try:
validate_endpoint(endpoint)
except:
print("Incorrect endpoint, expected <ip:port>")
sys.exit(1)
generate_server_conf(privkey, macs)
generate_th100ini(pubkey, endpoint)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment