Skip to content

Instantly share code, notes, and snippets.

@chris001
Forked from lrstanley/tunnel_4to6.py
Last active August 29, 2015 14:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chris001/52ea51062e854cc1a508 to your computer and use it in GitHub Desktop.
Save chris001/52ea51062e854cc1a508 to your computer and use it in GitHub Desktop.
"""
HE-2-4 Copyright (C) 2014 Liam Stanley
License: Eiffel Forum License, version 2
- https://links.ml/FFa1
Website: https://liamstanley.io
NOTE: THIS IS FOR KVM BASED SERVERS ONLY.
I'M NOT ADDING CUSTOM CHECKS TO SEE IF
YOU'RE USING KVM.
"""
import subprocess
import os
import re
import time
from datetime import datetime
# Tunnelbroker IPv6
server_ipv6 = '2001:470:1f10:e55::1'
# Tunnelbroker IPv4
server_ipv4 = '184.105.253.14'
# Routed /64 or /48 (WITH suffix) (i.e. the ::/64 or the ::/48 at the end)
bind_to_ip = '2001:470:c280::/48'
# Number of IPv6 to bind (as ::<bind number>) starting from 5 (to be safe)
bind_count = 95 # 95 means the last one will be ::100.
# Ignore shit after this line or expect something to break. Yep I said it.
re_ipv6 = r'(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))'
re_ipv4 = r'^[0-9]{2,3}\.[0-9]{2,3}\.[0-9]{2,3}\.[0-9]{2,3}$'
def main():
""" Do stuff here """
# First we need to ensure the data is sanitized and the end user isn't dumb.
global server_ipv6, server_ipv4, bind_to_ip, bind_count
server_ipv6 = server_ipv6.split('/', 1)[0].strip()
server_ipv4 = server_ipv4.strip()
bind_count += 5
if not re.match(re_ipv6, server_ipv6):
output('error', 'server_ipv6 seems to be an incorrect IPv6 address. Exiting!')
os._exit(1)
if not re.match(re_ipv4, server_ipv4):
output('error', 'server_ipv4 seems to be an incorrect IPv4 address. Exiting!')
os._exit(1)
if '::' not in bind_to_ip or '/' not in bind_to_ip:
output('error', 'bind_to_ip seems to not have the netmask attached!. Exiting!')
os._exit(1)
ip, netmask = bind_to_ip.split('::', 1)
if not re.match(re_ipv6, ip + '::'):
output('error', 'bind_to_ip seems to be an incorrect IPv6 address. Exiting!')
os._exit(1)
if not re.match(r'^\/[0-9]{2,3}$', netmask):
output('error', 'The netmask attached to bind_to_ip seems to be an incorrect netmask. Exiting!')
os._exit(1)
# Assume that the above is finally correct, and we can start attempting to bind
# Delete the old tunnel in case it's up
output('status', 'Taking down interface if it\'s already up...')
cmd('ip tun del sit1', ignore_errors=True)
# Bring up the interface
cmd('ifconfig sit0 up')
output('status', 'Bringing up a empty interface..')
# Connect the 4v6 tunnel to the IPv4-protocoled server
output('status', 'Adding connection to remote IPv4 tunneling server...')
cmd('ifconfig sit0 inet6 tunnel ::{server_ipv4};'.format(server_ipv4=server_ipv4))
# Bring up the interface that will hold all the sub-binded IPv6
output('status', 'Bringing up IPv6 tunnel interface...')
cmd('ifconfig sit1 up')
calc = str(float(0.03) * float(bind_count-5))
if '.' in calc:
first, second = calc.split('.', 1)
if len(second) > 2:
second[0:2]
calc = first + '.' + second
output('status', 'Binding {} IPv6 addresses. Estimated execution time: {} seconds.'.format(bind_count-5, calc))
# Loop through and add x amount of ips to bind to the above interface
for x in range(bind_count):
cmd('ifconfig sit1 inet6 add {ip}::{bind_number}{netmask}'.format(ip=ip, bind_number=x, netmask=netmask))
time.sleep(0.02)
output('status', 'Bound {} IPv6 addresses to {}...'.format(bind_count-5, ip))
# Bind the above interface to the IPv6 tunnel server
output('status', 'Adding connection to remote IPv6 tunneling server...')
cmd('ifconfig sit1 inet6 add {server_ipv6}::{netmask}'.format(server_ipv6=server_ipv6.split('::', 1)[0], netmask=netmask))
# Completion..
output('status', 'And last and least, enabling routing...')
cmd('route -A inet6 add ::/0 dev sit1')
output('status', 'Success!')
def docstring():
symbol = '*'
lines = __doc__.strip().split('\n')
largest = 0
for line in lines:
if len(line) > largest:
largest = len(line)
outer = (largest + (1 * 4)) * symbol
output('', outer)
for line in lines:
tmp = symbol + (1 * ' ') + line
sidedif = (largest + (1 * 4)) - len(tmp) - 1
tmp += ' ' * sidedif + symbol
output('', tmp)
output('', outer)
output('INIT', 'Initializing IPv6 bind script')
def cmd(command, ignore_errors=False, ignore_stdout=False):
"""
Execute some command that may or may not completely fuck up your system.
Jk's.
"""
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
if err:
output('error', str(err))
output('error', 'Exiting!')
os._exit(1)
return str(output), str(err)
def output(prefix, text):
""" Output text with a prefix. (sexify it) """
tn = datetime.now().strftime('%H:%M:%S')
if prefix:
print('[{}] [{}] {}'.format(tn, prefix, text))
else:
print('[{}] {}'.format(tn, text))
if __name__ == '__main__':
try:
docstring()
main()
except KeyboardInterrupt:
output('request', 'Requested to exit. You do not have to be mean!')
os._exit(0)
except Exception as e:
output('error', str(e))
output('error', 'Exiting!')
os._exit(1)

v4-to-v6 tunnel under KVM/dedi/OpenVZ

There are a few different method, for each different container. I think I've found the best methods for each, with tunnelbroker.net 6to4 tunnel && debian/Ubuntu

  • Note! For IRC usage, due to the large amount of abuse in accordance with tunnelbroker tunnels on IRC networks, tunnelbroker.net has disabled IRC traffic on their tunnels by default. This means you need ot signup for their certification test, (free), complete all test and get Sage certification. Once you get that, you can go into your system-specific tunnel, go to configuration, and enabled IRC usage on that tunnel. Easy as that!

OpenVZ

With OpenVZ, setting up a tunnel is quite a bit harder. This is because a lot of things are limited with the OVZ setup, to create dynamicy within kernel bounds.

  • Create a tunnel at tunnelbroker.net

Hurricane Electric allows creation of up to 5 free IPv6 tunnels @ tunnelbroker.net.

  • Create one for your VPS.
  • Enable TUN/TAP on your VPS.

It should normally be possible to do this through your control panel (e.g., SolusVM). If not, a support ticket with your provider should get it done fairly quickly. Be advised that toggling this option forces a reboot. So plan accordingly.

  • tb-tun (tb-userspace)

tb-tun is a userspace program that utilizes TUN/TAP to build a tunnelbroker tunnel on linux. Since we can’t do it any other way on a OpenVZ VPS.

sudo apt-get install iproute gcc
cd /root
wget http://tb-tun.googlecode.com/files/tb-tun_r18.tar.gz
tar -xf tb-tun_r18.tar.gz
gcc tb_userspace.c -l pthread -o tb_userspace
  • Create a new init script: nano /etc/init.d/ipv6tb and put in the following contents (after replacing the correct IP addresses, of course)

Remember, for the tunnel, your VPS IP is the client and the Hurricane Electric IP is the server.

#! /bin/sh
 
### BEGIN INIT INFO
# Provides:          ipv6
# Required-Start:    $local_fs $all
# Required-Stop:     $local_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the ipv6 tunnel 
# Description:       ipv6 tunnel start-stop-daemon
### END INIT INFO
 
# /etc/init.d/ipv6tb
 
touch /var/lock/ipv6tb
 
case "$1" in
  start)
    echo "Starting ipv6tb "
      setsid /root/tb_userspace tb [Server IPv4 Address] [Client IPv4 Address] sit > /dev/null 2>&1 &
      sleep 3s #ugly, but doesn't seem to work at startup otherwise
      ifconfig tb up
      ifconfig tb inet6 add [Client IPv6 Address]/64
      ifconfig tb inet6 add [Routed /64]::1/64 #Add as many of these as you need from your routed /64 allocation
      ifconfig tb mtu 1480
      route -A inet6 add ::/0 dev tb
      route -A inet6 del ::/0 dev venet0
    ;;
  stop)
    echo "Stopping ipv6tb"
      ifconfig tb down
      route -A inet6 del ::/0 dev tb
      killall tb_userspace
    ;;
  *)
    echo "Usage: /etc/init.d/ipv6tb {start|stop}"
    exit 1
    ;;
esac
 
exit 0
  • Make it executable, and add it to startup: chmod 0755 /etc/init.d/ipv6tb then update-rc.d ipv6tb defaults

  • Execute it right away: /etc/init.d/ipv6tb start OR simply reboot.

  • Test to confirm that IPv6 connectivity is working: ping6 -c 5 google.com

KVM (Or of the liking)

Credits for this simple script go to ChauffeR

<?php
    $v6 = "2001:470:1f12:500"; // Server IPv6 (without prefix)
    $server_ipv4 = "216.66.84.42"; // Server IPv4 (obviously)
    $bind = "2001:470:c957"; // Routed /64 or /48 (without prefix)
    
    shell_exec("ip tun del sit1");
    shell_exec("ifconfig sit0 up;ifconfig sit0 inet6 tunnel ::".$server_ipv4.";ifconfig sit1 up");
    for($i=5; $i<505; $i++){
            shell_exec("ifconfig sit1 inet6 add ".$bind."::".$i."/64");
            sleep(0.2);
    }
    shell_exec("ifconfig sit1 inet6 add ".$v6."::/64");
    shell_exec("route -A inet6 add ::/0 dev sit1");
?>

This will bind 500 or so of the first chunk of your IPv6. This can be put into a crontab at startup. Note, that this will also need php5-cli (sudo apt-get install php5 php5-cli)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment