{"id":883,"date":"2015-07-09T18:13:02","date_gmt":"2015-07-09T22:13:02","guid":{"rendered":"http:\/\/blog.jonesling.us\/?p=883"},"modified":"2015-07-09T20:55:54","modified_gmt":"2015-07-10T00:55:54","slug":"setting-up-a-gentoo-based-dual-stack-router","status":"publish","type":"post","link":"https:\/\/blog.jonesling.us\/?p=883","title":{"rendered":"Setting up a Gentoo-Based Dual-Stack Router"},"content":{"rendered":"<p>Our network has been based around a home-built router for quite some time, ever since I got fed up with the crappy ActionTec router that Verizon bundled with our FiOS service. (If you&#8217;re going to offer high-speed internet, you should probably bundle equipment that can actually keep up.) I had originally followed a slightly older version of <a href=\"https:\/\/wiki.gentoo.org\/wiki\/Home_Router\" target=\"_blank\">these instructions<\/a> to get a nice basic router going. But I finally wanted better. I wanted the bright, shiny, new thing. I wanted IPv6.<\/p>\n<p><strong>So, here&#8217;s my instructions for going from an existing IPv4 router to dual-stack IPv4\/6.<\/strong><\/p>\n<p>Note: I am using dnsmasq for DNS and DHCP, hostapd for wireless management, and an iptables firewall. Since Verizon still doesn&#8217;t widely support consumer IPv6, I&#8217;m using a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Tunnel_broker\" target=\"_blank\">tunnel broker<\/a> to get my \/6 address.  If you&#8217;re using a different setup your mileage may vary.  If you find anything that I appear to have forgotten, please let me know!<\/p>\n<h1>Step 1: Recompile the Kernel<\/h1>\n<p>This should be obvious: if you want to run ipv6 you need ipv6 support in your kernel. In order to trim as much off my kernel as possible I did not have it built in, and had to recompile.<\/p>\n<p>You should also add netfilter support for ipv6 so that your firewall will work.<\/p>\n<pre class=\"brush: plain; title: kernel changes; notranslate\" title=\"kernel changes\">\r\nNetworking support  ---&gt;\r\n    Networking options  ---&gt;\r\n        &lt;*&gt;   The IPv6 protocol  ---&gt;\r\n            &lt;*&gt;   IPv6: IPv6-in-IPv4 tunnel (SIT driver)\r\n        &#x5B;*] Network packet filtering framework (Netfilter)  ---&gt;\r\n            IPv6: Netfilter Configuration  ---&gt;\r\n                &lt;M&gt; IPv6 NAT\r\n                &lt;M&gt; IP6 tables support (required for filtering)\r\n                &lt;M&gt;   Packet filtering\r\n                &lt;M&gt;   ip6tables NAT support\r\n                &lt;M&gt;     MASQUERADE target support\r\n                ... other filtering options as you may need for your situation\r\n<\/pre>\n<h1>Step 2: Update Your IPv6 Support<\/h1>\n<p>Again, it was never compiled in, in order to trim off unused bits of code. Add &#8216;ipv6&#8217; to your USE variable and <code>emerge --newuse world<\/code><\/p>\n<h1>Step 3: Install network tools (if they aren&#8217;t already)<\/h1>\n<p><code>emerge --noreplace sys-apps\/iproute2 net-firewall\/iptables<\/code><\/p>\n<h1>Step 4 (optional): Set up your tunnel<\/h1>\n<p>If your ISP doesn&#8217;t provide ipv6, and many don&#8217;t, you need to request an address range from a tunnel broker. I&#8217;m using <a href=\"https:\/\/tunnelbroker.net\/\" target=\"_blank\">Hurricane Electric<\/a>, which is free, but there are others &#8212; see <a href=\"https:\/\/en.wikipedia.org\/wiki\/List_of_IPv6_tunnel_brokers\" target=\"_blank\">this list<\/a> or just <a href=\"https:\/\/www.google.com\/search?q=ipv6+tunnel+brokers&amp;ie=utf-8&amp;oe=utf-8\" target=\"_blank\">google it<\/a>.<\/p>\n<p>If you have multiple machines on your network (which is assumed, since this is a <em>router<\/em> guide), you may prefer a \/48, so that autoconfig works nicely, instead of the default \/64. This guide assumes a \/48.<\/p>\n<p>Going forward, replace <code>2001:470:891a:<\/code> with your own \/48 range.<\/p>\n<p>Now activate your tunnel:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nip tunnel add he-ipv6 mode sit remote 1.2.3.4 local 5.6.7.8 ttl 255\r\nip link set he-ipv6 up\r\nip addr add 2001:470:1f06:2a3::2\/64 dev he-ipv6\r\nip route add ::\/0 dev he-ipv6\r\nip -f inet6 addr\r\n<\/pre>\n<h1>Step 5: Update Your Net Config<\/h1>\n<p>I have two wired and one wireless card in my router. Here&#8217;s what my <code>\/etc\/conf.d\/net<\/code> looks like:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n# enp2s0 is my exterior wired nic (aka public facing)\r\n# enp3s5 is my interior wired nic\r\n# wlp3s6 is my interior wireless nic\r\n\r\ndhcp_enp2s0=&quot;nodns&quot; # we choose our own DNS, tyvm\r\n\r\nconfig_enp3s5=&quot;192.168.0.1\/24 2001:470:891a:0::\/64&quot;\r\n\r\nmodules_wlp3s6=&quot;!iwconfig !wpa_supplicant&quot;\r\nconfig_wlp3s6=&quot;192.168.1.1\/24 2001:470:891a:1::\/48&quot;\r\ndns_servers_wlp3s6=&quot;127.0.0.1&quot;\r\n<\/pre>\n<p>After making appropriate changes, restart your NICs. If you&#8217;re working remotely, you may want to be connected via two paths instead of just one (so when you inevitably get bounced and can&#8217;t reconnect, you still have a way back in).<\/p>\n<p>A properly-configured set of addresses looks like this:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n# ip addr\r\n1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default\r\n    link\/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\r\n    inet 127.0.0.1\/8 brd 127.255.255.255 scope host lo\r\n       valid_lft forever preferred_lft forever\r\n    inet6 ::1\/128 scope host\r\n       valid_lft forever preferred_lft forever\r\n2: enp2s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\r\n    link\/ether 00:e0:4d:bf:03:f5 brd ff:ff:ff:ff:ff:ff\r\n    inet 108.20.118.17\/24 brd 108.20.118.255 scope global enp2s0\r\n       valid_lft forever preferred_lft forever\r\n    inet6 fe80::cbdf:25c0:c948:f4bb\/64 scope link\r\n       valid_lft forever preferred_lft forever\r\n3: enp3s5: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000\r\n    link\/ether 00:04:5a:42:a6:98 brd ff:ff:ff:ff:ff:ff\r\n    inet 192.168.0.1\/24 brd 192.168.0.255 scope global enp3s5\r\n       valid_lft forever preferred_lft forever\r\n    inet6 2001:470:891a::\/64 scope global\r\n       valid_lft forever preferred_lft forever\r\n    inet6 fe80::204:5aff:fe42:a698\/64 scope link\r\n       valid_lft forever preferred_lft forever\r\n4: wlp3s6: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000\r\n    link\/ether 00:1a:ef:07:4d:a7 brd ff:ff:ff:ff:ff:ff\r\n    inet 192.168.1.1\/24 brd 192.168.1.255 scope global wlp3s6\r\n       valid_lft forever preferred_lft forever\r\n    inet6 2001:470:891a:1::\/64 scope global\r\n       valid_lft forever preferred_lft forever\r\n    inet6 fe80::21a:efff:fe07:4da7\/64 scope link\r\n       valid_lft forever preferred_lft forever\r\n5: sit0@NONE:  mtu 1480 qdisc noop state DOWN group default\r\n    link\/sit 0.0.0.0 brd 0.0.0.0\r\n6: he-ipv6@NONE: &amp;lt;POINTOPOINT,NOARP,UP,LOWER_UP&amp;gt; mtu 1480 qdisc noqueue state UNKNOWN group default\r\n    link\/sit 108.20.118.17 peer 209.51.161.14\r\n    inet6 2001:470:1f06:2a3::2\/64 scope global\r\n       valid_lft forever preferred_lft forever\r\n    inet6 fe80::6c14:7611\/64 scope link\r\n       valid_lft forever preferred_lft forever\r\n<\/pre>\n<p>Test it with a ping:<\/p>\n<p><code>ping6 www.kame.net<\/code><\/p>\n<h1>Step 6: Reconfigure dnsmasq<\/h1>\n<p>You&#8217;ll need to add router advertisments and your new addresses. Rather than hard-coding an address, dnsmasq offers a &#8216;constructor&#8217; label which figures it out automatically. Here&#8217;s the relevant section from my \/etc\/dnsmasq.conf:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndomain-needed\r\nbogus-priv\r\ndomain=jonesling.us\r\ndhcp-authoritative\r\nenable-ra\r\ndhcp-range=192.168.0.20,192.168.0.100,12h\r\ndhcp-range=192.168.1.20,192.168.1.100,12h\r\ndhcp-range=192.168.2.20,192.168.2.100,12h\r\ndhcp-range=::,constructor:enp3s5,ra-names,slaac,12h\r\ndhcp-range=::,constructor:wlp3s6,ra-names,slaac,12h\r\nresolv-file=\/etc\/resolv.dnsmasq\r\nselfmx\r\nenable-ra\r\n<\/pre>\n<p>And restart it: <code>\/etc\/init.d\/dnsmasq restart<\/code><\/p>\n<h1>Step 7: Configure your firewall<\/h1>\n<p>Pretty much every <code>iptables<\/code> reference in your firewall config will be mirrored with an <code>ip6tables<\/code> command.<\/p>\n<p>Here&#8217;s my script to set up iptables (if you see an error or something stupid, I would appreciate your criticism &#8211; paired with your reasoning on why it should be changed so I can know better for next time).<\/p>\n<pre class=\"brush: bash; auto-links: false; title: iptables.sh; notranslate\" title=\"iptables.sh\">\r\n#!\/bin\/bash\r\n# based on http:\/\/www.gentoo.org\/doc\/en\/home-router-howto.xml\r\n\r\n# set to '0' to lock the kids out\r\nOPEN_INTERNET=1\r\n\r\n# these systems can get shut out when OPEN_INTERNET isn't true\r\ndeclare -a NO_SURFING=( 'wii-u'\r\n                        'kids-computer'\r\n                      )\r\n\r\n# these systems never get shut out\r\ndeclare -a OK_SURFING=( 'parents-computer'\r\n                        'parents-phone'\r\n                      )\r\n\r\n# these ports take precedence over CLOSED_PORTS\r\ndeclare -a OPEN_TCP_PORTS=( 'ssh'\r\n                            'http'\r\n                            'mail'\r\n                            'submission'\r\n                          )\r\n\r\ndeclare -a OPEN_UDP_PORTS=( 'submission' )\r\n\r\n# if the port is meant to be closed, we close tcp *AND* udp\r\ndeclare -a CLOSED_PORTS=( '0:1055'\r\n                          'svn'\r\n                          'distcc'\r\n                          'x11'\r\n                          'nfs'\r\n                          'icpv2'\r\n                          'mysql'\r\n                          'rtsp'\r\n                          '3128' # squid\r\n                          '3130' # squid ICP\r\n                          '3551' # nisport\r\n                        )\r\n\r\ndeclare -a LAN_SERVICES=( &quot;svn&quot; )\r\n\r\n# blacklisted IPs and ranges\r\n# http:\/\/www.iana.org\/assignments\/ipv4-address-space\/ipv4-address-space.xhtml\r\ndeclare -a IP_BLACKLIST=( # APINIC\r\n                          # AFRINIC\r\n                          # LACNIC\r\n                          ...\r\n                        )\r\n\r\nLAN=enp3s5\r\nWLAN=wlp3s6\r\nWAN=enp2s0\r\nSIT=he-ipv6\r\n\r\nINSIDE=( $LAN $WLAN )\r\n\r\nLOCAL_RANGE_IPV4='192.168.0.0\/16'\r\nLOCAL_RANGE_IPV6='2001:470:891a::'\r\n\r\n# First we flush our current rules\r\niptables -F\r\niptables -t nat -F\r\nip6tables -F\r\nip6tables -t nat -F\r\n\r\n# Setup default policies to handle unmatched traffic\r\niptables  -P INPUT ACCEPT\r\niptables  -P OUTPUT ACCEPT\r\niptables  -P FORWARD DROP\r\nip6tables -P INPUT ACCEPT\r\nip6tables -P OUTPUT ACCEPT\r\nip6tables -P FORWARD DROP\r\n\r\n# Then we lock our services so they only work from the LAN\r\niptables  -I INPUT 1 -i ${LAN}  -j ACCEPT\r\niptables  -I INPUT 1 -i ${WLAN} -j ACCEPT\r\niptables  -I INPUT 1 -i lo      -j ACCEPT\r\nip6tables -I INPUT 1 -i ${LAN}  -j ACCEPT\r\nip6tables -I INPUT 1 -i ${WLAN} -j ACCEPT\r\nip6tables -I INPUT 1 -i lo      -j ACCEPT\r\n\r\n# block members of IP_BLACKLIST, plus any addresses passed in on the\r\n# command line\r\nfor IP in ${IP_BLACKLIST&#x5B;@]} ; do\r\n    iptables -I INPUT -s ${IP} -p TCP --dport ssh -j DROP\r\ndone\r\n\r\nfor IP in $@; do\r\n    iptables -I INPUT -s ${IP} -d 0\/0 -j REJECT\r\ndone\r\n\r\niptables  -A INPUT -p UDP --dport bootps -i ${WAN} -j REJECT\r\nip6tables -A INPUT -p UDP --dport bootps -i ${SIT} -j REJECT\r\niptables  -A INPUT -p UDP --dport domain -i ${WAN} -j REJECT\r\nip6tables -A INPUT -p UDP --dport domain -i ${SIT} -j REJECT\r\n\r\n# Explicitly allow access to services on the WAN\r\nfor SERVICE in ${LAN_SERVICES&#x5B;@]} ; do\r\n    for IFACE in ${INSIDE&#x5B;@]} ; do\r\n        iptables  -A INPUT -p TCP --dport svn -i ${IFACE} -j ACCEPT\r\n        iptables  -A INPUT -p UDP --dport svn -i ${IFACE} -j ACCEPT\r\n        ip6tables -A INPUT -p TCP --dport svn -i ${IFACE} -j ACCEPT\r\n        ip6tables -A INPUT -p UDP --dport svn -i ${IFACE} -j ACCEPT\r\n    done\r\ndone\r\n\r\n# Allow access to our server from the WAN\r\nfor PORT in ${OPEN_TCP_PORTS&#x5B;@]} ; do\r\n    iptables  -A INPUT -p TCP --dport $PORT -i ${WAN} -j ACCEPT\r\n    ip6tables -A INPUT -p TCP --dport $PORT -i ${SIT} -j ACCEPT\r\ndone\r\n\r\nfor PORT in ${OPEN_UPD_PORTS&#x5B;@]} ; do\r\n    iptables  -A INPUT -p UDP --dport PORT -i ${WAN} -j ACCEPT\r\n    ip6tables -A INPUT -p UDP --dport PORT -i ${SIT} -j ACCEPT\r\ndone\r\n\r\n# Drop TCP \/ UDP packets to privileged ports\r\nfor PORT in ${CLOSED_PORTS&#x5B;@]} ; do\r\n    iptables  -A INPUT -p TCP -i ${WAN} -d 0\/0 --dport ${PORT} -j DROP\r\n    ip6tables -A INPUT -p TCP -i ${SIT} -d 0\/0 --dport ${PORT} -j DROP\r\n\r\n    iptables  -A INPUT -p UDP -i ${WAN} -d 0\/0 --dport ${PORT} -j DROP\r\n    ip6tables -A INPUT -p UDP -i ${SIT} -d 0\/0 --dport ${PORT} -j DROP\r\ndone\r\n\r\niptables  -I FORWARD -i ${LAN} -d $LOCAL_RANGE_IPV4 -j ACCEPT\r\niptables  -A FORWARD -i ${LAN} -s $LOCAL_RANGE_IPV4 -j ACCEPT\r\nip6tables -I FORWARD -i ${LAN} -d $LOCAL_RANGE_IPV6 -j ACCEPT\r\nip6tables -A FORWARD -i ${LAN} -s $LOCAL_RANGE_IPV6 -j ACCEPT\r\n\r\nif (( OPEN_INTERNET )); then\r\n    echo 'yay, everybody gets internet'\r\n    iptables  -I FORWARD -i ${WLAN} -d $LOCAL_RANGE_IPV4 -j ACCEPT\r\n    iptables  -A FORWARD -i ${WLAN} -s $LOCAL_RANGE_IPV4 -j ACCEPT\r\n    ip6tables -I FORWARD -i ${WLAN} -d $LOCAL_RANGE_IPV6 -j ACCEPT\r\n    ip6tables -A FORWARD -i ${WLAN} -s $LOCAL_RANGE_IPV6 -j ACCEPT\r\nelse\r\n    echo &quot;boo, only ${OK_SURFING&#x5B;@]} get internet&quot;\r\n    for IP in ${OK_SURFING&#x5B;@]}; do\r\n        iptables -I FORWARD -i ${WLAN} -d $IP\/255.255.255.255 -j ACCEPT\r\n        iptables -A FORWARD -i ${WLAN} -s $IP\/255.255.255.255 -j ACCEPT\r\n    done\r\nfi\r\n\r\niptables  -A FORWARD -i ${WAN} -d $LOCAL_RANGE_IPV4 -j ACCEPT\r\nip6tables -A FORWARD -i ${WAN} -d $LOCAL_RANGE_IPV6 -j ACCEPT\r\n\r\niptables  -t nat -A POSTROUTING -o ${WAN} -j MASQUERADE\r\nip6tables -t nat -A POSTROUTING -o ${SIT} -j MASQUERADE\r\n\r\n# This is so when we boot we don't have to run the rules by hand\r\n\/etc\/init.d\/iptables save\r\n\/etc\/init.d\/ip6tables save\r\n\r\n# fail2ban should be reloaded after flushing iptables\r\n\/etc\/init.d\/fail2ban reload\r\n<\/pre>\n<h1>Step 8: Update your DNS<\/h1>\n<p>Add a AAAA record to your domain&#8217;s DNS record.\u00a0 You may have to keep this one up-to-date yourself.<\/p>\n<p>Interesting to note: you might be thinking &#8220;crap, what&#8217;s the ipv6 equivalent of these CNAME records?&#8221;\u00a0 Stop worrying, there isn&#8217;t.\u00a0 The CNAME is read like normal, but ipv6 clients will then look up the AAAA (instead of the A) record of the destination host.\u00a0 It just works.<\/p>\n<p>What?\u00a0 You built your own router but you don&#8217;t have your own domain?\u00a0 WTF is wrong with you?<\/p>\n<h1>Step 9: Reboot your clients<\/h1>\n<p>While I was working, I made a bunch of mistakes and my clients had multiple ipv6 addresses &#8211; making networking from them unstable as they didn&#8217;t necessarily know which address to use. Rebooting will clear them &#8211; and make sure your config is proper.<\/p>\n<p>At this point your clients should be in ipv6 and you&#8217;re gonna be all excited to see if work.\u00a0 Browsers take ipv6 addresses a little differently: <code><a href=\"http:\/\/[2001:470:1f06:2a3::2]\/\" target=\"_blank\">http:\/\/[2001:470:1f06:2a3::2]\/<\/a><\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Our network has been based around a home-built router for quite some time, ever since I got fed up with the crappy ActionTec router that Verizon bundled with our FiOS service. (If you&#8217;re going to offer high-speed internet, you should probably bundle equipment that can actually keep up.) I had originally followed a slightly older &hellip; <a href=\"https:\/\/blog.jonesling.us\/?p=883\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Setting up a Gentoo-Based Dual-Stack Router&#8221;<\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","wprm-recipe-roundup-name":"","wprm-recipe-roundup-description":"","advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[9],"tags":[137,158,145,157,156,83,159],"class_list":["post-883","post","type-post","status-publish","format-standard","hentry","category-linux","tag-dad-forgot-his-meds-again","tag-firewall","tag-gentoo","tag-home-router-project","tag-ipv6","tag-linux","tag-networking"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p4o3FW-ef","jetpack-related-posts":[],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/posts\/883","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=883"}],"version-history":[{"count":13,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/posts\/883\/revisions"}],"predecessor-version":[{"id":896,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/posts\/883\/revisions\/896"}],"wp:attachment":[{"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=883"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=883"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=883"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}