#!/usr/bin/env python3 from flask import Flask, request, redirect, url_for from werkzeug.middleware.proxy_fix import ProxyFix import os import sys import ipaddress import random import subprocess app = Flask(__name__) app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1) # where player are stored DB_DIR= "./db" PLAYER_DIR = os.path.join(DB_DIR, "players") NET_DIR = os.path.join(DB_DIR, "networks") REGULAR_PAGE = """ Who plays IPv6 games?

Who plays IPv6 games?

So who of us is able to use IPv6 and is interested in playing IPv6 games? If you want to register, simply submit your name below. Obviously, your name and IPv6 address will be publicly recorded.

You are player: {player}

Objective

The objective of this game is to get your hands dirty with IPv6. To play it, you only need an IPv6 connection and a spare /64 IPv6 network that you can freely configure.

Register

Your name:

Afterwards

Interested in playing IPv6 games are...

Open Source @ IPv6Onlyhosting

As usual this project is open source and you can find the source code on code.ungleich.ch. This website is running on the IPv6OnlyHosting.com infrastructure. """ NET_PAGE = """ Register your network

Register your network

For playing IPv6 games, you should have a free /64 network to play around with. Use the format 2001:db8::/64.

Register

Your network:
""" ADDR_CHECK_PAGE = """ Check your network

Check your network

To be able to prove that you control a network, we selected a random IP in it. Only if you can make that IPv6 address ping6-able, then we believe that you really control it.

You are: {player}

Your registered random IPv6 address in your network is {random_ip}. The result of the check is: {returncode} (0 mean s reachable, everything else is an error) and the output of the ping command is:

{output}
(we should really convert to jinja2 now) """ NO_NETWORK = """Sorry, this is not an IPv6 network""" NO_SLASH_64 = """Sorry, this is not a /64 IPv6 network""" NO_USER = """Sorry, you are not a user, you cannot check your IPv6 address. Register first""" def player_exists_at_address(address): fname = os.path.join(PLAYER_DIR, address) exists = False if os.path.exists(fname): exists = True return exists def addresses(): address_list = [] if os.path.isdir(PLAYER_DIR): address_list = os.listdir(PLAYER_DIR) return address_list def networks(): network_list = [] if os.path.isdir(NET_DIR): network_list = os.listdir(NET_DIR) return network_list def get_player_from_network(network): fname = os.path.join(NET_DIR, network, "address") with open(fname,"r") as fd: address = fd.readlines()[0].strip() return address def get_player_network(address): network = None for net in networks(): fname = os.path.join(NET_DIR, net, "address") with open(fname,"r") as fd: net_address = fd.readlines()[0].strip() if net_address == address: network = net return network def get_player_ip(address): random_ip = None network = get_player_network(address) if not network: return None fname = os.path.join(NET_DIR, network, "random_ip") if os.path.exists(fname): with open(fname,"r") as fd: random_ip = fd.readlines()[0].strip() return random_ip def get_player_name(address): fname = os.path.join(PLAYER_DIR, address) with open(fname, "r") as fd: name = fd.readlines() return name[0].strip() def save_player(name, address): fname = os.path.join(PLAYER_DIR, address) with open(fname, "w+") as fd: fd.write("{}\n".format(name)) def is_v6_network(network): is_network = True try: net = ipaddress.IPv6Network(network) except: is_network = False return is_network def is_v6_slash_64(network): is_64 = True try: net = ipaddress.IPv6Network(network) print("{} {}".format(net, network)) if not net.prefixlen == 64: is_64 = False except: is_64 = False return is_64 def get_random_ip(network): net = ipaddress.IPv6Network(network) addr_offset = random.randrange(2**64) addr = net[0] + addr_offset return addr def save_network(address, network): if not is_v6_network(network): return NO_NETWORK if not is_v6_slash_64(network): return NO_SLASH_64 if not os.path.isdir(NET_DIR): os.mkdir(NET_DIR) # get filesystem friendly name net_name = str(ipaddress.IPv6Network(network)[0]) dirname = os.path.join(NET_DIR, net_name) if not os.path.isdir(dirname): os.mkdir(dirname) fname = os.path.join(dirname, "address") with open(fname, "w+") as fd: fd.write("{}\n".format(address)) fname = os.path.join(dirname, "network") with open(fname, "w+") as fd: fd.write("{}\n".format(network)) random_ip = get_random_ip(network) fname = os.path.join(dirname, "random_ip") with open(fname, "w+") as fd: fd.write("{}\n".format(random_ip)) return redirect(url_for('net')) def identify_user(address): """ Find user by connecting IPv6 address """ player = None # found the player if player_exists_at_address(address): return address # check whether player is connecting from a registered network v6_addr = ipaddress.IPv6Address(address) for net in networks(): v6_net = ipaddress.IPv6Network("{}/64".format(net)) if v6_addr in v6_net: player = get_player_from_network(net) break return player @app.route('/check_addr', methods=['GET']) def check_addr(): address = request.remote_addr player = identify_user(address) if not player: return NO_USER random_ip = get_player_ip(player) s = subprocess.run(["ping", "-c1", random_ip], capture_output=True) return ADDR_CHECK_PAGE.format(player=player, random_ip=random_ip, returncode=s.returncode, output=s.stdout.decode("utf-8")) @app.route('/net', methods=['GET', 'POST' ]) def net(): if request.method == 'GET': return NET_PAGE else: network = request.form['network'] address = request.remote_addr return save_network(address, network) @app.route('/', methods=['GET', 'POST' ]) def main(): address = request.remote_addr if request.method == 'GET': html = [] player = identify_user(address) for address in addresses(): name = get_player_name(address) network = get_player_network(address) random_ip = get_player_ip(address) html.append("
  • {}@{}: net: {} random_ip: {}".format(name,address, network, random_ip)) return REGULAR_PAGE.format(player_list="\n".join(html), player=player) else: name = request.form['name'] save_player(name, address) return redirect(url_for('main')) if __name__ == '__main__': if not os.path.isdir(DB_DIR): os.mkdir(DB_DIR) app.run(host="::1", debug=False)