{"id":22,"date":"2017-05-07T03:43:13","date_gmt":"2017-05-07T03:43:13","guid":{"rendered":"http:\/\/blog.miguelsarmiento.com\/?p=22"},"modified":"2017-05-07T03:43:13","modified_gmt":"2017-05-07T03:43:13","slug":"dual-stack-ipv4-and-ipv6-with-fc","status":"publish","type":"post","link":"https:\/\/blog.miguelsarmiento.com\/?p=22","title":{"rendered":"Dual Stack IPV4 and IPV6 with FC"},"content":{"rendered":"<p>I use FC as my Internet router through Comcast. For the last 5 years I had run a 6to4 tunnel, but recently I read that Comcast was deploying IPV6 natively so I decided to give it a try.<\/p>\n<p>Hopefully my experience in transitioning to a dual stack using IPV4 and IPV6 from a 6to4 tunnel will help others.<\/p>\n<p><!--more--><\/p>\n<p>There are plenty of articles and blogs stating how to do it but my situation once again was a bit unique for the following reasons:<\/p>\n<ul>\n<li>I am running kernel 2.6.26, I know it is a bit behind but my motto is &#8220;if isn\u2019t broken do not fix it&#8221;. So as long as I patch software so I do not expose the server it is ok. Having an older kernel though will bite me.<\/li>\n<li>While I was running a 6to4 tunnel so IPV6 worked, DHCLIENT seem not to have IPV6 support, running DHCLIENT would not obtain a prefix for example. That was odd since it was supposed to have support.<\/li>\n<li>Some of the configurations I saw were for DEBIAN or (Ubuntu) but not FC although adapting them was easy enough.<\/li>\n<\/ul>\n<p>So I decided to take the plunge!<\/p>\n<p>The steps I show are not new, other blogs and forums have similar instructions for several devices. I decided to follow the ones in this <a href=\"http:\/\/www.phildev.net\/phil\/blog\/?p=308\">blog<\/a>, mainly because it was for Debian which could allow me to modify the scripts to run out of rc.local<\/p>\n<h4>Request an Address from Comcast<\/h4>\n<h5>Get a Prefix<\/h5>\n<p>I use BIND internally so I did recompile it so it would support IPV6 (so I could add HOST records to it, the subject hopefully of another post), and of course recompiled DHCLIENT and DHCLIENT-SCRIPT from the latest ICS software to make sure it would do what was needed.<\/p>\n<p>So next I did stop the 6to4 tunnel and rebooted (do not need to do that but wanted to make sure that no lingering routes remained and RADVD was not handling address).<\/p>\n<p>So first we need to know what addresses we are getting.<\/p>\n<p>You use DHCLIENT for that but you really want a prefix not jus and address and in addition you will be requesting a prefix on your WAN address but you will actually put that address on your LAN interface, confused? Do not be it will be explained shortly.<\/p>\n<p>So issue:<\/p>\n<pre class=\"csharpcode\">dhclient -P -d -v -1 $EXTERNAL_INTERFACE<style type=\"text\/css\">\r\n<p>.csharpcode, .csharpcode pre<br \/>\r\n{<br \/>\r\n\tfont-size: small;<br \/>\r\n\tcolor: black;<br \/>\r\n\tfont-family: consolas, \"Courier New\", courier, monospace;<br \/>\r\n\tbackground-color: #ffffff;<br \/>\r\n\t\/*white-space: pre;*\/<br \/>\r\n}<br \/>\r\n.csharpcode pre { margin: 0em; }<br \/>\r\n.csharpcode .rem { color: #008000; }<br \/>\r\n.csharpcode .kwrd { color: #0000ff; }<br \/>\r\n.csharpcode .str { color: #006080; }<br \/>\r\n.csharpcode .op { color: #0000c0; }<br \/>\r\n.csharpcode .preproc { color: #cc6633; }<br \/>\r\n.csharpcode .asp { background-color: #ffff00; }<br \/>\r\n.csharpcode .html { color: #800000; }<br \/>\r\n.csharpcode .attr { color: #ff0000; }<br \/>\r\n.csharpcode .alt<br \/>\r\n{<br \/>\r\n\tbackground-color: #f4f4f4;<br \/>\r\n\twidth: 100%;<br \/>\r\n\tmargin: 0em;<br \/>\r\n}<br \/>\r\n.csharpcode .lnum { color: #606060; }<\/style><\/pre>\n<p>You will see something like this:<\/p>\n<pre class=\"csharpcode\">ia-pd 88:27:52:e7 {\r\nstarts 1370574554;\r\nrenew 157751;\r\nrebind 252402;\r\niaprefix $PREFIX::\/64 {\r\n starts 1370574554;\r\n preferred-life 315503;  \r\n max-life 315503;\r\n }\r\n}<\/pre>\n<p>The important detail here is &#8220;iaprefix&#8221; follow by the actual network that Comcast is giving you.<\/p>\n<h5>Assign an Address to your Internal Interface<\/h5>\n<p>So configure the $INTERNAL_INTERFACE with an IP address like:<\/p>\n<pre class=\"csharpcode\">ip addr add $PREFIX::1\/64 dev $INTERNAL_INTERFACE<\/pre>\n<p>So if the prefix is 2001:A:A:A::0\/64 then use 2001:A:A:A::1\/64.<\/p>\n<h5>Accept Router Advertisements<\/h5>\n<p>Now you need to accept Router Advertisements (RA) from Comcast so FC knows how to route to the internet. This is where having an old kernel bit me.<\/p>\n<p>The RFC states that if you are a router you shouldn\u2019t accept router advertisements (RA) the rationale being that you are a router or you are a host, but you are not both. Thus, even if you set net.ipv6.conf.all.accept_ra=1, if you also have ip_forward=1, Linux will silently drop all RAs.<\/p>\n<p>In our case, however we want to accept router advertisements on our external interface and send our own router advertisements on our internal interface.<\/p>\n<p>Fortunately, Linux added a new value to accept_ra which accepts RAs even if ip_forward is on and that value is 2.<\/p>\n<p>Sadly, in kernels before that was added (anything before 2.6.37), a value of 2 is accepted, but it has no benefit (it\u2019s treated the same as 1). In these older kernels you can set ip_forward=0 on the external interface and 1 on the internal interface and packets will still be forwarded and you will accept RAs. See <a href=\"http:\/\/strugglers.net\/~andy\/blog\/2011\/09\/04\/linux-ipv6-router-advertisements-and-forwarding\/\">this blog<\/a> for more information.<\/p>\n<p>So you need to disable forwarding:<\/p>\n<pre class=\"csharpcode\">sysctl -w net.ipv6.conf.$EXTERNAL_INTERFACE.forwarding=0<\/pre>\n<p>Then set RA to 2:<\/p>\n<pre class=\"csharpcode\">sysctl -w net.ipv6.conf.$YOUR_EXTERNAL_INTERFACE.accept_ra=2<\/pre>\n<p>You should now have connectivity. Try pinging ipv6.google.com.<\/p>\n<p>How are we routing? Well via the link-local address on our external interface since it receives a Router Notification of where to send packets (this is how IPV6 routes, there is not need to set a default route).<\/p>\n<h5>Set Radvd for Internal Hosts<\/h5>\n<p>IPV6 will use auto-configuration when allowed. This is done using the Router Advertisement Daemon (RADVD). Install it if you do not have it.<\/p>\n<p>Then open \/etc\/radvd.conf and set the following:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">interface<\/span> INTERNAL_INTERFACE {\r\nAdvSendAdvert on;\r\nRDNSS 2001:4860:4860::8888 2001:4860:4860::8844 {};\r\nprefix PREFIX\r\n{\r\nAdvOnLink on;\r\nAdvAutonomous on;\r\n};\r\n};<\/pre>\n<p>This configuration uses Google DNS servers. Now start radvd.<\/p>\n<h4>Automate Everything<\/h4>\n<p>Of course you would not like to this every time that you reboot so you need a few scripts at boot time.<\/p>\n<h5>Make the scripts<\/h5>\n<p>First a script to obtain the prefix, you need a second instance of DHCLIENT that requests a prefix:<\/p>\n<pre class=\"csharpcode\">#!\/bin\/bash\r\n\r\nIFACE=<span class=\"str\">\"external interface\"<\/span>\r\n\r\n# If there<span class=\"str\">'s a stale dhclient, kill it\r\npid=`ps -ef | awk '<\/span>\/[d]hclient -6\/{print $2}'`\r\n\/bin\/kill $pid\r\n\r\n# Start our <span class=\"kwrd\">new<\/span> one\r\n\/sbin\/dhclient -6 -P -1 -pf \/var\/run\/dhclient6.$IFACE.pid \\\r\n-lf \/var\/lib\/dhclient\/dhclient6.$IFACE.leases $IFACE &amp;\r\n\r\nexit 0<\/pre>\n<p>Save it as start-dhclient, make it executable and call it from \/etc\/rc.local for example so it will be run at boot.<\/p>\n<p>Now save the following script as ipv6 and also run it after start-dhclient.<\/p>\n<pre class=\"csharpcode\">#!\/bin\/bash\r\n#\r\n# For radvd, it takes \/etc\/radvd.conf.tmpl, replaces <span class=\"str\">\"__PREFIX__\"<\/span> with your\r\n# prefix, and - <span class=\"kwrd\">if<\/span> it<span class=\"str\">'s different from \/etc\/radvd.conf - replaces the config\r\n# file and restarts the daemon.\r\n#\r\n\r\nINT_IFACE=\"LAN Interface\"\r\nEXT_IFACE=\"WAN Interface\"\r\n\r\nLEASE=\"\/var\/lib\/dhclient\/dhclient6.$EXT_IFACE.leases\"\r\n\r\nnew_ip6_prefix=$(tail $LEASE | \/usr\/bin\/awk '<\/span>\/iaprefix\/ {print $2}<span class=\"str\">')\r\n\r\ncurrent_ip=$(\/sbin\/ip -6 addr show dev $INT_IFACE scope global |\\\r\n\/usr\/bin\/awk '<\/span>\/inet6\/ {print $2}<span class=\"str\">')\r\n\r\ncurrent_prefix=$(echo $current_ip | \/bin\/sed -e '<\/span>s@::1\/64@::\/64@<span class=\"str\">')\r\n\r\nif [ \"$current_prefix\" == \"$new_ip6_prefix\" ] ; then\r\necho \"Prefix is the same. Nothing to do\"\r\nexit\r\nfi\r\n\r\n# Setup the new IP\r\necho \"Prefix is different or IPV6 address not setup. Setting up\"\r\nnew_ip=$(echo $new_ip6_prefix | \/bin\/sed -e '<\/span>s@::\/64@::1\/64@g<span class=\"str\">')\r\n\r\nif [ ! -z \"$current_ip\" ] ; then\r\n\/sbin\/ip -6 addr del $current_ip dev $INT_IFACE\r\nfi\r\n\r\n\/sbin\/ip -6 addr add $new_ip dev $INT_IFACE\r\n\r\n# Ensure we'<\/span>ll get router advertisements\r\n\/sbin\/sysctl -w <span class=\"str\">\"net.ipv6.conf.$EXT_IFACE.accept_ra=2\"<\/span>\r\n\r\n# Needed <span class=\"kwrd\">for<\/span> kernels before 2.6.37, don't worry,\r\n# forwarding will still work <span class=\"kwrd\">as<\/span> <span class=\"kwrd\">long<\/span> <span class=\"kwrd\">as<\/span> you have it set\r\n# on your other <span class=\"kwrd\">interface<\/span>.\r\n\r\n\/sbin\/sysctl -w <span class=\"str\">\"net.ipv6.conf.$EXT_IFACE.forwarding=0\"<\/span>\r\n\r\n# Update radvd\r\n\r\ntmpfile=\/tmp\/radvd.conf.$$\r\nsed -e <span class=\"str\">\"s@__PREFIX__@$new_ip6_prefix@g\"<\/span> \/etc\/radvd.conf.tmpl &gt; $tmpfile\r\ndiff $tmpfile \/etc\/radvd.conf &gt;\/dev\/<span class=\"kwrd\">null<\/span>\r\n\r\n<span class=\"kwrd\">if<\/span> [ $? == 1 ]; then\r\nmv $tmpfile \/etc\/radvd.conf\r\n\/etc\/init.d\/radvd restart\r\n<span class=\"kwrd\">else<\/span>\r\nrm $tmpfile\r\nfi<\/pre>\n<p>Create a file called \/etc\/radvd.conf.tmpl as follows:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">interface<\/span> INTERNAL_INTERFACE {\r\nAdvSendAdvert on;\r\nRDNSS 2001:4860:4860::8888 2001:4860:4860::8844 {};\r\nprefix __PREFIX__\r\n{\r\nAdvOnLink on;\r\nAdvAutonomous on;\r\n};\r\n};<\/pre>\n<p>The script ipv6 does the following:<\/p>\n<ul>\n<li>Assigns an IP from the prefix to the internal interface<\/li>\n<li>Sets forwarding and ra accordingly<\/li>\n<li>Configures radvd<\/li>\n<\/ul>\n<p>Finally check periodically that our prefix has not changed, drop ipv6 and start-dhclient under \/etc\/crond.daily so they run every night at 4 am. I have found that is often enough otherwise you need to check more often.<\/p>\n<h4>Final Thoughts<\/h4>\n<p>After doing above you should have a dual stack.<\/p>\n<ul>\n<li>You need to call DHCLIENT twice once for IPV4 and once for IPV6.<\/li>\n<li>You need to allow UDP traffic for DHCP requests, to 546, from 547 on the link-local address network fe80::\/64.<\/li>\n<li>Unfortunately unless we run Dynamic DNS if the prefix changes your DNS entries will be wrong.<\/li>\n<li>Finally and I cannot stress this enough you need to have IP6TABLES running as soon as you have IPV6 working correctly. Otherwise your devices will be exposed to the Internet.<\/li>\n<\/ul>\n<p>Happy dual stack.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I use FC as my Internet router through Comcast. For the last 5 years I had run a 6to4 tunnel, but recently I read that Comcast was deploying IPV6 natively so I decided to give it a try. Hopefully my experience in transitioning to a dual stack using IPV4 and IPV6 from a 6to4 tunnel &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/blog.miguelsarmiento.com\/?p=22\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Dual Stack IPV4 and IPV6 with FC&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-22","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blog.miguelsarmiento.com\/index.php?rest_route=\/wp\/v2\/posts\/22","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.miguelsarmiento.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.miguelsarmiento.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.miguelsarmiento.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.miguelsarmiento.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=22"}],"version-history":[{"count":1,"href":"https:\/\/blog.miguelsarmiento.com\/index.php?rest_route=\/wp\/v2\/posts\/22\/revisions"}],"predecessor-version":[{"id":23,"href":"https:\/\/blog.miguelsarmiento.com\/index.php?rest_route=\/wp\/v2\/posts\/22\/revisions\/23"}],"wp:attachment":[{"href":"https:\/\/blog.miguelsarmiento.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=22"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.miguelsarmiento.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=22"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.miguelsarmiento.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=22"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}