Scope#

Raspberry is exposed to the internet for my backup solution. I want to enable ipv6 access only and enable access only from my home computer.
Steps:
  1. register your home computer at a dyndns service to provide the current ipv6, I used dynv6.com
  2. create windows batch script to update dynv6
  3. schedule windows batch script to run each time the PC is booted
  4. on raspberry create iptables ruleset
  5. use python script to query the current ipv6 from dynv6 and replace in iptables ruleset
  6. schedule the ipv6 update on raspberry

iptables#

Commands#

> ls -la /usr/sbin/ip*  # list all commands, there are many
> iptables*             # for ipv4 (in debian busters = nft)
> ip6tables*            # for ipv6 (in debian busters = nft)
> iptables-legacy       # former ones, not nft
> iptables-nft          # directly use nft
Notes:
  • all iptables commands (for ipv4) have an ip6tabbles* equivalent (for ipv6)
  • see info on nft
> who -u                      # get all sessions with ip and pid
> sudo netstat -pantW         # list network connections, p=programs,a=all,n=IPs,t=tcp,W=wide(not truncate IP address) 
> ip a                        # list all ips
> sudo ip6tables -L -v        # list all ipv6 rules
> sudo ip6tables -n -v --line-numbers -L     # list all ipv6 rules with numeric IPs and rule number

Syntax#

see docu
> sudo iptables -L -v 
> sudo iptables -n -v --line-numbers -L 
> sudo service iptables start		# activate firewalling
> sudo service ip6tables start
> sudo chkconfig iptables on		# enable after reboot
> sudo chkconfig ip6tables on
iptables [-t <table-name>] <command> <chain-name> <parameter-1>  <option-1> <parameter-n> <option-n>
  • table-name
    • like [filter, nat, mangle, raw, security], if omitted we use "filter"
  • command
    • -F : flush current chain or all if omitted
    • -X : deletes a user-specified chain or all if omitted
    • -Z : zeros the byte and packet counters in all chains
    • -A : apppend a rule at the end
    • -I : inserts at a specified position (similar to replace -R), wihtout position at the top
    • -P : a policy is a fall back and is used after all rules have passede** you can enable certain special addresses earlier
    • -L : list all rules
  • chain-name
    • INPUT, FORWARD, OUTPUT (as listed with > iptables -L)
    • you may invent new chain names, but this seems not to be common (command -N)
  • parameter-1 (filter)
    • -s : source filter (address[/mask][...])
    • -d : destination filter
    • -p : protocoll filter like [icmp, tcp, udp, all] or those in /etc/protocols, if omitted ALL protocols are considered
      • with -p tcp you can use --dport for destination port filter, any number
      • with -p udp you can use --dport for destination port and --sport as source port filter
      • ports can be also a range like 3000:3200 (all from 3000 to 3200)
      • with -p icmp you can use --icmp-type
    • -i : interface like [eth0, lo, ppp0], without name ALL interfaces are used
    • -j : jump to [ACCEPT, DROP, QUEUE, RETURN] (or others added with modules)
    • -m : adds a comment when listing the rules, syntax >-m comment --comment "My comments here"<
  • option-1 (target)
    • [ACCEPT, DROP, QUEUE, RETURN] (or others added with modules)
  • option-n (listing options)
    • -v : verbose output
    • -n : displays IP addresses and port numbers in numeric format instead of hostname/network service
  • notes
    • the first three commands are usually used to create a fresh ruleset in a script
    • in the chain list and then drop all other later

my general ruleset#

#!/bin/bash

# MARKUS

#SOURCE=2a02:5a0:4110:f590:fdd3:3e99:a137:852c
SOURCE=::

# ipv4 ------------------------------------
# Flush all rules and delete all chains for a clean startup
iptables -F
iptables -X
iptables -Z             # Zero out all counters

# drop all ipv4 traffic, we want to use ipv6 only
iptables -A INPUT -s 1.1.1.1 -j ACCEPT
iptables -A OUTPUT -d 1.1.1.1 -j ACCEPT
iptables -A INPUT -s 8.8.8.8 -j ACCEPT
iptables -A OUTPUT -d 8.8.8.8 -j ACCEPT

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -j DROP
iptables -A FORWARD -j DROP
iptables -A OUTPUT -j DROP

# ipv6 ------------------------------------
# Flush all rules and delete all chains for a clean startup
ip6tables -F
ip6tables -X
ip6tables -Z

# drop all ipv6 traffic, except EbelStube
# do not limit to --dport 22, because the source has random ports (?)
# add first to enabel replacing 1. rule later
ip6tables -A INPUT  -s $SOURCE -j ACCEPT
ip6tables -A OUTPUT -d $SOURCE -j ACCEPT

# allow ipv6 local loopback
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

# drop everthing else
ip6tables -P FORWARD DROP               # as policy generally
ip6tables -A INPUT  -j DROP
ip6tables -A OUTPUT -j DROP

# update first ip6tables rules and enable my computer
python update_ip6tables.py

Python#

  • package "python3-iptables" manages legacy ones only, docu1, docu2
  • package "python3-nftables" manages nft tables, docu
  • alternatively you can use subprocess.run to call the original system commands

subprocess#

import socket   # determine ipv6
import subprocess

tupel = socket.getaddrinfo('your.pc.com', None, socket.AF_INET6)
# tupel like [(<AddressFamily.AF_INET6: 23>, 0, 0, '', ('2a02:5a0:4110:f590:4670:d3e6:f2bc:ee', 8384, 0, 0))]
print("tupel=", tupel)

ipv6=tupel[0][4][0]
print("ipv6=", ipv6)

subprocess.run(["/usr/sbin/ip6tables", "-R", "INPUT", "1", "-s", ipv6, "-j", "ACCEPT"])
subprocess.run(["/usr/sbin/ip6tables", "-R", "OUTPUT", "1", "-d", ipv6, "-j", "ACCEPT"])

Windows batch script to update dynv6 service#

REM update_dynv6.bat

REM set utf-8
chcp 65001      

echo off
ipconfig

rem for /F "tokens=2 delims=:" %%i in ('"ipconfig | findstr Temporäre | findstr 2a02:"')  do echo %%i
for /F "tokens=9" %%i in ('"ipconfig | findstr Temp | findstr 2a02"')  do set ipv6=%%i

echo ---------- extracting Temporäre IPv6-Adresse ----------
echo ipv6=%ipv6%

set url="http://dynv6.com/api/update?hostname=your.domain.here^&token=yourTokenHere&ipv6=%ipv6%"

ECHO Updating IPv6
curl "%url%"

echo:
echo done
pause