Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


Help with IPV6 Bridge settings Debian/Hetzner
New on LowEndTalk? Please Register and read our Community Rules.

All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.

Help with IPV6 Bridge settings Debian/Hetzner

nobizzlenobizzle Member
edited July 2017 in Help

Hi,

I'm going to pull my hair out. Can anybody help with a working IPV6 setup for host and guest on a bridged system on a dedicated server? IPV4 works like a charm, but I just don't know what to do with this ipv6 setup.

Thanks in advance.

My current setup on the host:

auto lo
iface lo inet loopback

auto vmbr0
iface vmbr0 inet static
address 1.2.3.4
netmask 255.255.255.255
pointopoint 1.2.3.1
gateway 1.2.3.1
bridge_ports enp4s0
bridge_stp off
bridge_fd 1
bridge_hello 2
bridge_maxage 12

iface vmbr0 inet6 static
address 2a01:4f8:1234:1234::1
netmask 64
gateway fe80::1

up ip route add IP.v4.local.route dev vmbr0
up ip -6 route add 2a01:4f8:1234:1234::/64 dev vmbr0  

auto vmbr1
iface vmbr1 inet static
address 192.168.0.10
netmask 255.255.255.0
bridge_ports none
bridge_stp off
bridge_fd 0

post-up iptables -t nat -A POSTROUTING -s '192.168.0.0/24' -o vmbr0 -j MASQUERADE
post-down iptables -t nat -D POSTROUTING -s '192.168.0.0/24' -o vmbr0 -j MASQUERADE

on the guest:

The loopback network interface
auto lo
iface lo inet loopback

The primary network interface
auto ens19
iface ens19 inet static
address 192.168.0.2/24
gateway 192.168.0.1
dns-nameservers 192.168.0.1 8.8.8.8

auto ens18
iface ens18 inet static
address 1.2.3.5
netmask 255.255.255.255
pointopoint 1.2.3.1
gateway 1.2.3.1

iface ens18 inet6 static
address 2a01:4f8:1234:1234::2
gateway fe80::1
netmask 64

Comments

  • MikePTMikePT Moderator, Patron Provider, Veteran

    PM me if you need me to fix this for you. I bill a few beers though... ;]

    Thanked by 1nobizzle
  • I sympathize with your pain on this issue. I've had my own strange issues with IPv6 on Hetzner.

    Here's the setup I have that works for me. At one point I was having issues with IPv6 link-local addresses so that's why my configuration manually adds it. I believe it should be taken care of automatically though if you ignore it.
    If you are still having issues, I recommend checking to see what's happening using tcpdump. e.g. tcpdump -i eth0 ip6

    Note that I "reuse" the 2a01:4f8:1234:1234::1 IPv6 address on the host for both eth0 and br0. However I only add the /128 to eth0 and add the entire /64 subnet to br0.

    In my configuration the bridging is handled by libvirt so that part isn't shown.

    For each virtual machine I allocate a /112 (yes, I know this isn't technically correct but Hetzner charges extra if you want more than a /64 subnet).
    e.g. virtual machine 1 is: 2a01:4f8:1234:1234::1:1/112
    virtual machine 2 is: 2a01:4f8:1234:1234::2:1/112
    ...

    settings on host:

    root@server:/home/server# sysctl net.ipv6.conf.eth0
    <some settings snipped>
    net.ipv6.conf.eth0.accept_dad = 1
    net.ipv6.conf.eth0.accept_ra = 0
    net.ipv6.conf.eth0.accept_redirects = 1
    net.ipv6.conf.eth0.accept_source_route = 0
    net.ipv6.conf.eth0.autoconf = 0
    net.ipv6.conf.eth0.disable_ipv6 = 0
    net.ipv6.conf.eth0.forwarding = 1
    

    Host /etc/network/interfaces:

    <snipped some IPv4 stuff>
    
    iface eth0 inet6 static
    address 2a01:4f8:1234:1234::1
    netmask 128
    gateway fe80::1
    # Add the link-local address that matches the specific MAC
    up ip -6 addr add dev eth0 scope link fe80::21e:67ff:fea0:3ada
    
    auto br0
    iface br0 inet static
    address 10.5.5.1
    netmask 255.255.255.224
    network 10.5.5.0
    bridge_stp off
    bridge_maxwait 5
    bridge_ports none
    bridge_fd 0
    up ip addr add 2a01:4f8:1234:1234::1/64 dev br0
    up ip addr add fe80::1/64 dev br0 scope link
    down ip addr del fe80::1/64 dev br0 scope link
    down ip addr del 2a01:4f8:1234:1234::1/64 dev br0
    

    Virtual machine /etc/network/interfaces:

    # The primary network interface
    allow-hotplug eth0
    iface eth0 inet static
    address 10.5.5.5
    netmask 255.255.255.224
    network 10.5.5.0
    broadcast 10.5.5.31
    gateway 10.5.5.1
    up ip addr add 2a01:4f8:1234:1234::1:1/112 dev eth0
    up ip -6 route add default via fe80::1 dev eth0
    down ip -6 route del default via fe80::1 dev eth0
    down ip addr del 2a01:4f8:1234:1234::1:1/112 dev eth0
    
  • nobizzlenobizzle Member
    edited July 2017

    @goinsj2010 said:
    I sympathize with your pain on this issue. I've had my own strange issues with IPv6 on Hetzner.

    Here's the setup I have that works for me. At one point I was having issues with IPv6 link-local addresses so that's why my configuration manually adds it. I believe it should be taken care of automatically though if you ignore it.
    If you are still having issues, I recommend checking to see what's happening using tcpdump. e.g. tcpdump -i eth0 ip6

    Note that I "reuse" the 2a01:4f8:1234:1234::1 IPv6 address on the host for both eth0 and br0. However I only add the /128 to eth0 and add the entire /64 subnet to br0.

    In my configuration the bridging is handled by libvirt so that part isn't shown.

    For each virtual machine I allocate a /112 (yes, I know this isn't technically correct but Hetzner charges extra if you want more than a /64 subnet).
    e.g. virtual machine 1 is: 2a01:4f8:1234:1234::1:1/112
    virtual machine 2 is: 2a01:4f8:1234:1234::2:1/112
    ...

    Hey @goinsj2010:

    Thank you for your kind reply.. I gotta admit that I'm only slowly getting into this IPv6 stuff and when I read your reply, I realize that I'm missing a lot of knowledge. Just to defend myself, this is just a hobby of me and so I do not claim to be an expert at all :)

    The link local address is always the fe80 address which is given to a device automatically upon activating it? So I kinda route the traffic over this local address and then forward it to the actual given 64 (or whatever) net?

    So I just tried to make it with those settings (of course changing values to my needs) but it either doesnt work or I messed up somehow. Maybe you can get into detail a little bit more :]

  • Hi @nobizzle

    Don't worry if the IPv6 stuff is new to you. I can't claim to be an expert either so hopefully my advice on this topic is correct. I'm honestly not sure if IPv6 is more complicated than IPv4 or if we are just so familiar with the "old" way that it feels easier.

    My understanding regarding the link-local addresses are that they provide a way to communicate with other hosts on the same physical link (or bridge). Normally a link-local address is automatically given to an interface based on its MAC address. As far as I know, the primary usage of these addresses is so that you can automatically communicate with routers on the same link and autoconfigure your global IP and other settings. Essentially, this allows IPv6 to implement the same behavior as DHCP.

    In our case we don't really want the autoconfiguration part since Hetzner assigns you a static subnet of IPv6 addresses. To make configuration easier for you, Hetzner does a little "trick" and always assigns the link-local address of "fe80::1" to their routers. So no matter what physical server they give you, you can safely assume that the router is located at that IPv6 address.

    So as far as debugging, I'd suggest first making sure that IPv6 works on your physical server and then progressing to make sure it works for your virtual servers.

    First things first, on your host server if you run the command

    sysctl net.ipv6.conf.eth0
    

    do you get the same values that I showed in my previous post?
    If not, you can change them for future reboots using something like the following:

    cat <<EOF >> /etc/sysctl.d/local.conf
    net.ipv6.conf.all.forwarding=1
    net.ipv6.conf.eth0.autoconf=0
    net.ipv6.conf.eth0.accept_ra=0
    net.ipv6.conf.eth0.disable_ipv6=0
    EOF
    

    Then restart your server and re-run the sysctl command to view the settings and make sure they are correct.

    Now let's see if you can communicate with the local Hetzner IPv6 router. In a terminal window use the command

    tcpdump -n -vv -i eth0 ip6 host fe80::1
    

    Now in another terminal window (while tcpdump is running) try executing the command

    ping6 -c 3 -I eth0 fe80::1
    

    This is asking your server to ping the link-local address fe80::1 (e.g. the Hetzner router) using the eth0 interface. Note that the ping command had to specify which interface we were talking about since we asked about a link-local address.

    Here are the results I get. In this example, the 3ada address is the link-local address assigned to my server's eth0 interface.

    root@server:/home/server# tcpdump -n -vv -i eth0 ip6 host fe80::1
    tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
    16:13:21.844322 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32)
    fe80::21e:67ff:fea0:3ada > fe80::1: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has fe80::1
    <snip>
    16:13:21.847145 IP6 (class 0xc0, hlim 255, next-header ICMPv6 (58) payload length: 24) fe80::1 > fe80::21e:67ff:fea0:3ada: [icmp6 sum ok] ICMP6, neighbor advertisement, length 24, tgt is fe80::1, Flags [router, solicited]
    16:13:26.129470 IP6 (hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::21e:67ff:fea0:3ada > fe80::1: [icmp6 sum ok] ICMP6, echo request, seq 1
    16:13:26.129926 IP6 (hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::1 > fe80::21e:67ff:fea0:3ada: [icmp6 sum ok] ICMP6, echo reply, seq 1
    16:13:27.128465 IP6 (hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::21e:67ff:fea0:3ada > fe80::1: [icmp6 sum ok] ICMP6, echo request, seq 2
    16:13:27.128898 IP6 (hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::1 > fe80::21e:67ff:fea0:3ada: [icmp6 sum ok] ICMP6, echo reply, seq 2
    16:13:28.128338 IP6 (hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::21e:67ff:fea0:3ada > fe80::1: [icmp6 sum ok] ICMP6, echo request, seq 3
    16:13:28.128764 IP6 (hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::1 > fe80::21e:67ff:fea0:3ada: [icmp6 sum ok] ICMP6, echo reply, seq 3
    

    Awesome! We got a response from the router. Now if the default IPv6 route is set to fe80::1 on eth0, then we should be able to communicate with any global IPv6 addresses.

    root@server:/home/server# ip -6 route show
    2a01:4f8:1234:1234::1 dev eth0  proto kernel  metric 256
    fe80::/64 dev eth0  proto kernel  metric 256 
    default via fe80::1 dev eth0  metric 1024 <-- this is important!
    

    On the host server, an attempt to ping global IPv6 addresses should now work (assuming DNS works).

    root@server:/home/server# ping6 -c 3 ipv6.google.com
    PING ipv6.google.com(fra16s07-in-x0e.1e100.net) 56 data bytes
    64 bytes from fra16s07-in-x0e.1e100.net: icmp_seq=1 ttl=56 time=4.88 ms
    64 bytes from fra16s07-in-x0e.1e100.net: icmp_seq=2 ttl=56 time=4.90 ms
    64 bytes from fra16s07-in-x0e.1e100.net: icmp_seq=3 ttl=56 time=5.10 ms
    

    If everything works to this point then let me know and you can start debugging the virtual server connectivity.

    Thanked by 4WSS nobizzle Falzo MasonR
  • @goinsj2010 said:
    Hi @nobizzle
    ...
    If everything works to this point then let me know and you can start debugging the virtual server connectivity.

    To make it short for this answer: Everything is exactly like its described in your last post. This is really huge.. i learned a lot from it! I'm looking forward on what to do next ^^ thank you so far!

  • Okay, so IPv6 is working on the host.

    Now for the virtual server setup. Insert caveat here... I use a bridged network configuration with KVM managed using libvirt/virsh. I'm not sure on the specifics of your usage but hopefully my example will provide enough guidance to lead you in the right direction.

    For example, in my .xml configuration file that's used by virsh to define the KVM guest I have the following lines:

    <interface type='bridge'>
       <mac address='52:54:00:EF:7E:9F'/>   <-- should be different for each guest
       <source bridge='br0'/>
       <model type='virtio'/>
    </interface>
    

    Your configuration may be different. On the host machine I can verify that my guest machines are connected to the bridge on interface vnet1, vnet2, and vnet3.

    root@server:/home/server# brctl show
    bridge name bridge id       STP enabled interfaces
    br0     8000.fe5400ef2558   no      vnet1
                                        vnet2
                                        vnet3
    

    Since you said that IPv4 works properly, I'm assuming that your bridge configuration is already correct.

    Now for the IPv6 configuration part. Let's start by copying the same strategy as Hetzner and adding a custom link-local IPv6 address of "fe80::1" to our bridge. This will be the address that we will use as the router for our virtual guests.

    On the Host machine I have the following in /etc/network/interfaces (reiterated from my original post):

    <snipped some IPv4 stuff>
    
    auto eth0
    iface eth0 inet6 static
        address 2a01:4f8:1234:1234::1
        netmask 128
        gateway fe80::1
        # Add the link-local address that matches the specific MAC
        up ip -6 addr add dev eth0 scope link fe80::21e:67ff:fea0:3ada
    
    auto br0
    iface br0 inet static
        address 10.5.5.1
        netmask 255.255.255.224
        network 10.5.5.0
        bridge_stp off
        bridge_maxwait 5
        bridge_ports none
        bridge_fd 0
        up ip addr add 2a01:4f8:1234:1234::1/64 dev br0
        up ip addr add fe80::1/64 dev br0 scope link
        down ip addr del fe80::1/64 dev br0 scope link
        down ip addr del 2a01:4f8:1234:1234::1/64 dev br0
    

    Notice that I assigned "2a01:4f8:1234:1234::1" to eth0 with a /128 subnet and also assigned the same IPv6 to br0, except with a /64 subnet. You don't have to do it this way (in fact it's probably more correct to assign a different IP address like "2a01:4f8:1234:1234::2" to the br0 interface). My inexperience with IPv6 is starting to show, so others will have to correct me if I've given you bad advice.

    The important thing is that the /64 subnet is assigned to the br0 interface. This way the host server knows that any traffic for that IP range should be forwarded to the bridge.

    If everything works correctly, the bridge should now have 1) a global static IPv6 address, 2) an automatic link-local address based on its MAC address, and 3) the "fe80::1" address that we manually assigned.

    Here's my example:

    root@server:/home/server# ip -6 addr show br0
    3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 
        inet6 2a01:4f8:1234:1234::1/64 scope global 
               valid_lft forever preferred_lft forever
        inet6 fe80::1/64 scope link 
               valid_lft forever preferred_lft forever
        inet6 fe80::302a:fff:fee3:46e8/64 scope link 
               valid_lft forever preferred_lft forever
    

    The host machine should also be routing the traffic accordingly:

    root@server:/home/server# ip -6 route show
    2a01:4f8:1234:1234::1 dev eth0  proto kernel  metric 256 
    2a01:4f8:1234:1234::/64 dev br0  proto kernel  metric 256 
    fe80::/64 dev eth0  proto kernel  metric 256 
    fe80::/64 dev br0  proto kernel  metric 256 
    fe80::/64 dev vnet1  proto kernel  metric 256 
    fe80::/64 dev vnet2  proto kernel  metric 256 
    fe80::/64 dev vnet3  proto kernel  metric 256 
    default via fe80::1 dev eth0  metric 1024
    

    Now we can double check our virtual server network configuration. As noted previously, I personally split up the IPv6 allocation with a /112 subnet for each guest.

    Guest 1 gets the IPv6 range 2a01:4f8:1234:1234::1:0000 --> 2a01:4f8:1234:1234::1:FFFF
    Guest 2 gets the IPv6 range 2a01:4f8:1234:1234::2:0000 --> 2a01:4f8:1234:1234::2:FFFF
    ... and so on.
    

    In the first guest machine, the /etc/network/interfaces file looks like this:

    # The loopback network interface
    auto lo
    iface lo inet loopback
    
    # The primary network interface
    allow-hotplug eth0
    iface eth0 inet static
        address 10.5.5.5
        netmask 255.255.255.224
        network 10.5.5.0
        broadcast 10.5.5.31
        gateway 10.5.5.1
        up ip addr add 2a01:4f8:1234:1234::1:1/112 dev eth0
        up ip -6 route add default via fe80::1 dev eth0
        down ip -6 route del default via fe80::1 dev eth0
        down ip addr del 2a01:4f8:1234:1234::1:1/112 dev eth0
    

    Notice that I am doing two things. First, I add the /112 subnet to the interface. Second, I am also instructing the KVM guest to use "fe80::1" as the default gateway. Since this is a link-local address it's actually going to connect to the br0 interface on the host machine. The host machine will then route the packet to the "fe80::1" address of the Hetzner router.

    The routing table of the guest KVM machine:

    root@guest:/home/user# ip -6 route show
    2a01:4f8:1234:1234::1:0/112 dev eth0  proto kernel  metric 256 
    fe80::/64 dev eth0  proto kernel  metric 256 
    default via fe80::1 dev eth0  metric 1024
    

    It's finally time to test everything! After configuring everything as above, restart the host for good measure. I've previously had strange issues while configuring IPv6 with Hetzner and I'm becoming superstitious and starting to think that Hetzner sometimes "gives up" when sending traffic to your server (if the server isn't configured properly) and stops routing packets to the machine. I've never had issues after getting it set up correctly and waiting an hour or two.

    Anyways, let's verify that packets are getting routed to you correctly. Use a different computer with IPv6 connectivity and try pinging the virtual server from the internet:

    On the host machine:

    tcpdump -n -i eth0 ip6 host 2a01:4f8:1234:1234::1:1
    

    Ping the IPv6 address (corrected with your IP info) and see what happens.

    Hopefully the traffic will be routed through the internet to your server and you will see the ping request (and maybe even a ping response) in the tcpdump output. Now log into the guest virtual machine and try checking IPv6 connectivity. It should all work. If not, try debugging by running tcpdump on the br0 interface to make sure that packets are being forwarded correctly by the host machine.

    Good luck!

    Thanked by 2MasonR Falzo
  • @goinsj2010 said:
    ...

    Hey, first of all. Thanks for this superb tutorial. Really interesting and detailed. Lots of respect for taking the time to write this down. I love LET.

    I did not have a lot of time yesterday, but i tried a little bit to make a few more steps.

    On the host side everything seems to be as you described.

    When trying to configure the VM guest, the machine does not come up with any IPv6 address. Is there a part missing in the given Guest config file?

    I'll try again later and come back with more detailed information.

    Again: Thank you!

    Best regards

  • nobizzle said: When trying to configure the VM guest, the machine does not come up with any IPv6 address. Is there a part missing in the given Guest config file?

    In the guest configuration posted above I manually assigned the IPv6 details using the "ip" command. You could also try using the standard /etc/network/interfaces syntax and see if that works for you.

    auto eth0
    iface eth0 inet6 static
        address 2a01:4f8:1234:1234::1:1
        netmask 112
        gateway fe80::1
    

    The IPv6 info should still appear in the output of the "ip" command on the guest:

    root@guest:/home/user# ip -6 addr show eth0
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
        inet6 2a01:4f8:1234:1234::1:1/112 scope global 
            valid_lft forever preferred_lft forever
        inet6 fe80::5054:ff:feef:7e9f/64 scope link 
            valid_lft forever preferred_lft forever
    

    If everything is correct we should see the global IPv6 address that you manually assigned as well as the link-local address that was auto-assigned based on the MAC address.

    Thanked by 1Falzo
  • First of all: sorry for the late response. The tutorial you wrote down here is just plain awesome! Thanks again!

    Ok, I feel a little bit ashamed for not being able to realize the given solution in your last post on my own.. But yeah. IPv6 is now up and running. Partly.

    I've been working on this for quite some time now. And i gotta admit that I'm pissed.

    Whatever configuration I use, I end up with either having IPv4 on bot machines, or IPv6 on both machines. The best thing I could achieve was IPv4 and IPv6 on the host and IPv6 on the guest only.. I just don't know what to do anymore.

    I'll try a little bit more tonight, but I almost gave up on it. If I can't make it, I'll post some of my settings I had the last few days..

    Thanked by 1Falzo
  • Hmm, that's strange. As far as I know, IPv6 and IPv4 in Linux are completely independent so enabling one should have no affect on the other.

    The only time I've encountered behavior like you describe is when I've installed firewall software (Shorewall) on the host. For example, if you install an IPv4 firewall, sometimes IPv6 gets disabled by default.

    If you're comfortable giving me sudo or root access pm me and I can log in to help you. It sounds like you are really close to having everything working.

  • nobizzlenobizzle Member
    edited July 2017

    Ok.. it took me several days. I neglected my girlfriend and job, but i finally made it. And damn, it's actually VERY easy. Here is my solution:


    HOST:

    source-directory /etc/network/interfaces.d
    
    auto lo
    iface lo inet loopback
    
    auto vmbr0
    iface vmbr0 inet static
    address 1.2.3.10
    netmask 255.255.255.224
    gateway 1.2.3.1
    pointopoint 1.2.3.1
    bridge_ports eth0
    bridge_stp off
    bridge_maxwait 5
    
    up ip route add 1.2.3.11/32 dev vmbr0
    down ip route del 1.2.3.11/32 dev vmbr0
    
    iface vmbr0 inet6 static
    address 2a01:4f8:1234:1234::2
    netmask 64
    gateway fe80::1
    
    bridge_ports eth0
    bridge_stp off
    bridge_maxwait 5
    
    auto vmbr1
    iface vmbr1 inet static
    address 10.0.1.1
    netmask 255.255.255.0
    bridge_ports none
    bridge_stp off
    bridge_fd 0
    
    post-up iptables -t nat -A POSTROUTING -s '10.0.1.0/24' -o vmbr0 -j MASQUERADE
    post-down iptables -t nat -D POSTROUTING -s '10.0.1.0/24' -o vmbr0 -j MASQUERADE
    

    GUEST:

    auto eth0
    iface eth0 inet static
    address 1.2.3.11
    netmask 255.255.255.224
    gateway 1.2.3.10
    
    iface ens18 inet6 static
    address 2a01:4f8:1234:1234::3
    netmask 64
    gateway 2a01:4f8:1234:1234::2
    
    auto ens19
    iface ens19 inet static
    address 10.0.1.2
    netmask 255.255.255.0
    gateway 10.0.1.1
    

    Don't forget the sysctl settings posted above. But now the funny part:

    I don't want to change anything now, as is finally works and it took me A LOT of time to find this easy soltution, but in Proxmox I had to set the network interface to VMware vxnet on the guest. Not Intel (My server has a Intel card), not virtio. This one works.

    Have fun with it. Peace I'm out.

    Thank you, guys!

Sign In or Register to comment.