Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Guide: home router with dual stack IPv4/IPv6 (brouter)
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks
View previous topic :: View next topic  
Author Message
skaloo
n00b
n00b


Joined: 18 Jul 2014
Posts: 7

PostPosted: Fri Jul 18, 2014 4:50 pm    Post subject: Guide: home router with dual stack IPv4/IPv6 (brouter) Reply with quote

Hi everybody,

Foreword: apologies for any english mistake, not an english-native speaker.

Disclaimer: my network topology and my choices are mine only, I don't pretend this is the *best* way to do things (any comment on that part is welcome), but that's how I decided to do it and I will eventualy give a couple reasons further down the post. Also, I do not intend to explain everything step-by-step as imho this kind of setup is not trivial and someone who's reading this has basic knowledge of gentoo/linux/networking. Feel free to ask for details. The post is more intended to save people with similar goals a lot of reading of deprecated or complex things on the internet when there is a decently easy solution it took me a couple days to find, set up and test -- see below for details.

Tags: home router - IPv6 - dual stack - dhcp - dns - dnsmasq - brouter - iptables - ip6tables - ebtables - bridge

Note: To skip all the chitchat about why I did it that way: search for "At (long) last: HOWTO"

Preamble: the 'why' and the roots of the 'how'

A few days ago, I decided to finaly migrate my home network to IPv4/IPv6 dual stack as my provider is actualy offering native IPv6 for a while. I had postponed this migration mostly because of security issues as IPv6 basicaly gives all your hosts 'public' addresses and I didn't have the hardware and time to deal with that.

Old IPv4 only topology: (( The Internet )) ... [ISP ADSL Router] ... { my hosts }

That network was easy to manage, the router did all the work: DHCP-ing all hosts private IPv4 addresses, NAT-ing, DNAT-ing (port-forward) a few services, DNS-relaying and so on.

The main reason why I postponed going IPv6 was I didn't want to bother managing security on all my hosts (I have quite a bunch of them, as I work at home and use an extensive number of VMs and physical hosts). I could of course have disabled IPv6 on all hosts I didn't want to manage, but then what is the point having an IPv6-enabled network ;)

Anyway, the idea to ease network management of all my hosts is to have a linux box in between the router and the actual LAN that will do most of the firewalling job (and some of the automatic-configuring too).

So the new topology will be: (( The Internet )) ... [ISP ADSL Router] ... [Linux Box] ...{ my hosts }

I bought a barebone PC with 2 network interfaces and a USB3-Gigabit adapter in order the linux box to have 3 NICs and completely isolate the various links (router, dmz, lan). What is required then is to have the Linux box fulfill the following services:
  • giving addresses to internal hosts (both IPv4 and IPv6)
  • providing some DNS relaying (or caching)
  • firewalling all coms between the 3 network branches


Having done some years of sysadmin in the past, IPv4 wasn't a problem at all, but I admit I hadn't read much on IPv6 yet, so first things first: RTFM :p I spent a few hours searching the web for infos, examples, documentations on IPv6 and related stuff, and to my surprise, most articles were *old* and often outdated. And that's the main reason behind this post, I ended up doing what I think is a neat and easy setup, but had to dig through tons of articles to put it together properly (which is odd considering how simple it is in the end).
So, let's start with the easy bit...

IPv4: the old trusted thing

I will shamelessly bypass details on the IPv4 configuration, mostly because it doesn't have much in terms of tricky details. It's just an old trusted classical IPv4 router with dnsmasq as the DHCP/DNS server and iptables doing filtering + DNAT + SNAT.

[ISP Router]192.168.1.1 ... 192.168.1.2[Linux box]172.16.0.1 ... 172.16.0.0/16{LAN hosts} ++ 172.17.0.1 ... 172.17.0.0/16{DMZ hosts}

My router has a specific setting that makes it transfer all 'incoming' connections to a given IPv4 address. The alternative would have been to define DNAT rules for *all* IPv4 services I need to serve. Lucky me ! I didn't have to do that :)

Anyway, enough of IPv4, this is not the real target of the post, so onto...

IPv6: shiny !

My findings were sometimes confusing, I've read many things on 'radvd', IPv6 routing, router advertisement, neighbor detection protocol, and so on... But something kept tickling my brain... IPv6 is all about giving 'public' addresses to all hosts. The ISP actualy allocates your router some sub-net (generaly a /64 or /56) that you are supposed to use for all your hosts on a 'flat' model. This is called the 'prefix' in IPv6 documentations. Technically, if I was working on an IPv4 network with the same premices, I would have 2 choices: sub-net the allocated network and route it or... bridge it ! In the world of IPv6, sub-netting the prefix given by your ISP ain't really a good idea, and it can actualy break some protocols (IPv6 auto-config works only on /64 as far as I know), and to make things worse, changing the linux box into a true IPv6 router is actualy not so easy (not so well supported as of now). IPv6 includes some additionnal protocols to deal with automatic routing (router advertisement, neighbor detection, ...) but all those are seldomly supported and simply not needed if you bridge ! Bridging also removes the need of IPv6 allocations as the ISP router will do it.
So the question is now: is it possible to do bridging while retaining the IPv4 routing ?
And luckily the answer is: YES !
That was the key in my decision process, everything became easier and more straight-forward.

So the final idea is:
  • each physical interface has *only* an IPv4 address
  • a bridge covering all the physical interfaces is created and has only an IPv6 address (for the linux box itself)


The problem is then to tell the kernel what to route and what to bridge: here comes 'ebtables'. 'ebtables' is a tool similar to 'iptables' but aimed at dealing specificaly with bridging. For the gory details, I'll point you to an internet serach, suffice to say that 'ebtables' filtering kicks in very early in the packet flow (and at a low protocol level too), allowing the kernel to split IPv4 and IPv6 processing in order to do exactly what's needed here.

At (long) last: HOWTO

Required kernel options (this was done on a basic gentoo installation, kernel 3.12.21):
  • Networking support
    • Networking options
      • Network packet filtering framework (Netfilter)
        • Advanced netfilter configuration (required to display some options we'll need)
          • Bridged IP/ARP packets filtering (not sure this is needed, didn't have time to check w/o it)
          • Core Netfilter Configuration
            • ... anything you want for your filewall...
            • "physdev" match support (this will allow to match ip6 packets on the bridge ports)

          • Ethernet Bridge tables (ebtables) support
            • ebt: broute table support
            • ebt: IP6 filter support
            • ...anything else you may need...

        • 802.1d Ethernet Bridging


Required tools:
  • net-misc/bridge-utils
  • net-firewall/iptables
  • net-firewall/ip6tables
  • net-firewall/ebtables
  • opt. sys-apps/iproute2 - many (old) documentations strongly suggest using iproute2 over ifconfig when dealing with IPv6; I'm not sure if that really matters anymore, ifconfig always seemed to work fine for me during the first hours of my testing though I ended up installing iproute2 and didn't try the end configuration w/o it
  • opt. dhcp client of your choice - this is only needed if you want your uplink interface to get its IPv4 address from the router dynamically


I'm not going to go through the required steps to configure network cards and make them go up at boot time and so on, this is well explained in the 'gentoo handbook' and in the 'modular networking' documents. I'll just show my /etc/conf.d/net file:
Code:
#
# bridge ip6
#
bridge_br0="www0 lan0 dmz0"
config_br0="null"

#
# tweaks on order & who's providing 'net'
#
rc_net_br0_need="net.www0 net.lan0 net.dmz0"
rc_net_lo_provide="!net"
rc_net_lan0_provide="!net"
rc_net_dmz0_provide="!net"
rc_net_br0_provide="!net"

#
# www net: get IP from ISP router
#
config_www0="dhcp"
dhcp_www0="nodns"

#
# lan net
#
config_lan0="172.16.0.1/16"

#
# dmz net
#
config_dmz0="172.17.0.1/16"

#
# dns
#
dns_domain="skal.home"
dns_search="skal.home"
dns_servers="localhost"


Also in /etc/sysctl.conf, we need to disable IPv6 on the physical interfaces, and enable IPv4 forwarding:
Code:
# enable ip4 forwading
net.ipv4.ip_forward = 1

# disable ip6 on physical interfaces
net.ipv6.conf.www0.disable_ipv6 = 1
net.ipv6.conf.lan0.disable_ipv6 = 1
net.ipv6.conf.dmz0.disable_ipv6 = 1


And the real magic comes with ebtables, using the BROUTING chain of the 'broute' table (usage is similar to iptables). The documentation signals that even if it uses the classical DROP and ACCEPT targets, they have a special meaning in there: DROP means actualy 'route that packet', while ACCEPT means 'bridge that packet'. I went for policy DROP and injected an accept for IPv6:
Code:
ebtables -t broute -P BROUTING DROP
ebtables -t broute -A BROUTING -p ipv6 -j ACCEPT


Note: you can simply type those 2 commands in a shell then '/etc/init.d/ebtables save' and provided you added ebtables to boot time with rc-update you'll never have to bother with that again.

I strongly suggest you then set up firewall rules matching your needs, because any host inside your network will now get a (public) IPv6 address and start being visible to the world.

I personaly did a few scripts to deal with that (including the above ebtables setup).
There's no much point listing my whole iptables, but here are a few key points:
  • do IPv4 rules just as you would if you didn't have IPv6 at all, including DNAT & SNAT
  • IPv6 auto-configuration is done using icmpv6 and using 'link-local addresses', so in order to allow these w/o exposing your hosts to public ping you can filter with these 2 rules (the first one is for the linux box itself and the second for all your internal hosts):
    Code:
    ip6tables -A INPUT -s fe80::/10 -p ipv6-icmp -j ACCEPT
    ip6tables -A FORWARD -s fe80::/10 -p ipv6-icmp -j ACCEPT

  • when you want to filter IPv6 bridged packets, you need to use the 'physdev' match extension (that's why I did put it in the required kernel options), here's an example to allow HTTP traffic to the linux box from the LAN hosts:
    Code:
    ip6tables -A INPUT -m physdev --physdev-in lan0 -p tcp --dport http -j ACCEPT

    and another example to allow LAN hosts talking to the world:
    Code:
    ip6tables -A FORWARD -m physdev --physdev-in lan0 --physdev-out www0 -j ACCEPT


Note: my firewall policies are to DROP all INPUT and FORWARD, and that's why I need to explicitly ACCEPT the allowed coms. The last example wouldn't be required with an 'ACCEPT' policy for the FORWARD table for instance.

---

Ok, this is it. Hopefully this will be useful to a few people around the world.

PS: Gentoo rocks, keep up the good work folks.

--- edit addendum ---

In the process of adding a few screenshots - will be posted below


Last edited by skaloo on Sat Jul 26, 2014 4:04 am; edited 3 times in total
Back to top
View user's profile Send private message
szatox
Guru
Guru


Joined: 27 Aug 2013
Posts: 394

PostPosted: Fri Jul 18, 2014 9:05 pm    Post subject: Reply with quote

THere is some good info, indeed. Thanks for new ideas :)
However, you might want to reconsider some other things:
Bridged interfaces work a bit like a network switch. The bridge has it's own logic, and that logic works in the ethernet layer. Both, IP4 and IP6 are higher layers than ethernet. That means, if you bridge 2 interfaces, you can't really isolate networks. As a test, try manually set some other IP to hosts on different (but bridged) lans. I bet they will be able to ping each other even though your firewall forbids it.
Then, why would you assign IP4 to every interface you have? Does it mean you have 1 interface per zone and you want to assign different IP pools to them?

Second thing, AFAIR link-local adresses in IP6 are not routable. Do you assign e.g. site-local or global IPs to your hosts? Seems no. So do you use ipv6 to connect to the outer world? Your ISP supports IP6? I'm really curious, IPv6 seems to be gaining popularity in a very, VERY slow pace.
Back to top
View user's profile Send private message
NeddySeagoon
Administrator
Administrator


Joined: 05 Jul 2003
Posts: 32172
Location: 56N 3W

PostPosted: Fri Jul 18, 2014 9:25 pm    Post subject: Reply with quote

Moved from Networking & Security to Documentation, Tips & Tricks.

Its one of these, so moved here now that there has been a response.
_________________
Regards,

NeddySeagoon

Computer users fall into two groups:-
those that do backups
those that have never had a hard drive fail.
Back to top
View user's profile Send private message
skaloo
n00b
n00b


Joined: 18 Jul 2014
Posts: 7

PostPosted: Fri Jul 18, 2014 9:30 pm    Post subject: Reply with quote

Quote:
The bridge has it's own logic, and that logic works in the ethernet layer.

Yep, but that's where 'ebtables' work too.
(( see http://en.wikipedia.org/wiki/Iptables#mediaviewer/File:Netfilter-packet-flow.svg ))
'ebtables' basicaly allows me to force any IPv4 packet received on the bridge interface (which means on any physical interface, as my bridge covers them all) to the network layer while IPv6 packets remain on the link layer for bridging. So IPv4 packets are never bridged. And that's why my interfaces each have an IPv4 address. For IPv4, the linux box just acts as an old-school router: different networks on the different interface, ip_forward in the kernel and all.
For IPv6 packets though, they remain at the link layer (unless their destination is the br0 interface itself, through its IPv6 addresses), and the magic is that the ip6tables filter table is used there too (you can see it on the diagram, green tables are iptables while blue ones are ebtables) so any packet I want to filter out can be stopped by the bridge too.

Quote:
Second thing, AFAIR link-local adresses in IP6 are not routable. Do you assign e.g. site-local or global IPs to your hosts? Seems no. So do you use ipv6 to connect to the outer world? Your ISP supports IP6? I'm really curious, IPv6 seems to be gaining popularity in a very, VERY slow pace.


My ISP gives my router a whole block of /64 'public' IPv6 address, that's called delegation I think and as far as I understood the docs, that's the way it's meant to be in the IPv6 world.
Any host on my network may now enable IPv6 and gain one of those public addresses (that's done through auto-configuration which is part of the IPv6 system, nothing to configure !).
And that works, I tested it extensively using various IPv6-enabled websites, and online ping tools.

But you're true, IPv6 is being adopted very slowly, and that's another reason why I had postponed my migration.
Back to top
View user's profile Send private message
skaloo
n00b
n00b


Joined: 18 Jul 2014
Posts: 7

PostPosted: Fri Jul 18, 2014 9:31 pm    Post subject: Reply with quote

NeddySeagoon wrote:
Moved from Networking & Security to Documentation, Tips & Tricks.

Its one of these, so moved here now that there has been a response.


Thanks, and apologies for the misplacement.
Back to top
View user's profile Send private message
skaloo
n00b
n00b


Joined: 18 Jul 2014
Posts: 7

PostPosted: Fri Jul 18, 2014 9:57 pm    Post subject: Reply with quote

szatox wrote:
Thanks for new ideas :)


I'm not the inventor, I merely gathered up infos from different (many!) sources and got them up-to-date.

What I didn't mention though is why I went down that road instead of the slightly more documented 'radvd' way.

'radvd' and similar tools are based upon the 'router advertisement' part of the IPv6 protocol. But in order for this to work, you also need to support the 'neighbor detection' protocol. Both are supported to some extend by existing tools (radvd, dnsmasq with some options, ndppd, ...), but documentation & support on those are scarse and clumsy. In the best case I would have to install and configure semi-manualy 2 daemons to do something that is simply not required. And those daemons were quite 'noisy' when I tried them, lots of chit-chat between the routers, lots of logs for some of them... What I mean is: I found all that very cumbersome, convoluted and inefficient.
The bridge way on the other hand is imho quite slick & neat: don't even have any daemon running, as all is done in the kernel tables.
Back to top
View user's profile Send private message
skaloo
n00b
n00b


Joined: 18 Jul 2014
Posts: 7

PostPosted: Sat Jul 19, 2014 8:22 am    Post subject: Reply with quote

A few screenshots to show the results.

Server interfaces config: http://postimg.org/image/efmc8oh5j/
Key points:
  • the physical interfaces (www0,lan0,dmz0) only have IPv4 addresses
  • link & global IPv6 addresses on br0


Server pinging the IPv6 world: http://postimg.org/image/cmq4ulkub/

Server firewall rules excerpt: http://pastebin.com/jKLFzy2F
Key points:
  • not an ultra secured firewall, work in progress and only here to show a couple key points
  • classical IPv4 rules using the physical interfaces, including DNAT and SNAT (masquerade)
  • allows ICMPv6 on link-local segment for IPv6 auto-configuration (not any other incoming ICMP, will be shown below)
  • IPv6 rules use the PHYSDEV match extension
  • the ebtables rule and policy at the end


An host config (lan segment): http://postimg.org/image/9nahzddj7/
Key points:
  • win7 assigns 2 different IPv6 addresses using the public prefix (classical one made using the MAC address, plus a 'temporary' one)
  • IPv4 address in the proper lan network 172.16.0.0/16
  • IPv4 DNS server is the linux box


Win7 host pinging the IPv6 world: http://postimg.org/image/469dnd53p/

Now to check the bridge is filtering the incoming packets, I used some online IP6 ping tool to ping my network from outside:


And finaly the well-known test-ipv6.com website results:
http://postimg.org/image/5ihh1ubon/
http://postimg.org/image/lbr0w1nzb/

The warning about the browser is not an error, I specificaly configured it to prefer IPv4 a while ago. During my testings, I was using a VM with a non-modified browser and there wasn't any warning.
Note that my provider doesn't actualy offer any IPv6 DNS, but the website still shows that part ok. That's because my hosts use the Linux box as DNS, and my dnsmasq is configured to use both IPv6 and IPv4. It even has an IPv6 DNS uplink, though that's not mandatory for the test to pass.
Back to top
View user's profile Send private message
szatox
Guru
Guru


Joined: 27 Aug 2013
Posts: 394

PostPosted: Sat Jul 19, 2014 9:11 pm    Post subject: Reply with quote

Well, good job gathering that info then :)
There is some buzz about IPv6, but it still hard to find anyone who would actually know how it works, so gratz on your patience during all the research you had to do.
Building a hybrid router/bridge device is an interesting idea, and indeed with both, iptables and ebtables it seems to have a good chance to work.

Ebtables uses an insane command line convention though, so double and tripple check it before using. Prefferably with a sniffer :)
I've run a brief search for ebtables docs, and they are inconsistent.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum