IPv6

From SME Server
Jump to navigation Jump to search

IPv6 implementation on Koozali SME Server

Some notes on how we can implement IPv6 on Koozali SME Server

This is a massive task and needs careful consideration and a lot of work.

Initial bug: https://bugs.koozali.org/show_bug.cgi?id=6393

Feel free to add notes and comments.


  Warning:
Code below is highly experimental. Do NOT try it on a production server.


Commentary

As IPv4 address availability has decreased, the world is slowly starting to use IPv6.

A fundamental block to adoption of IPv6 has been the lack of backwards compatibility. Yes, you could go full IPv6 only, assuming all your devices can handle it, but as most of the world still runs IPv4 you have to manage that.

Essentially every service and app has to be written to allow for both IPv4 AND IPv6. aka 'Dual Stack'.

That means duplicating a lot of work, and due to the nature of IPv6 - it was not designed to handle NAT, and every device is meant to have a routable public IP - this means added complexity and security considerations. That makes it more difficult for Koozali in Server/Gateway mode.

Carriers have found it easier to use CGNAT - double NAT - than deal with the issue of rolling out IPv6.

Some countries have rolled IPv6 out, some are in the process, and many have not at all.

Even where IPv6 has been rolled out, not all ISPs offer it.

IPv6 has been around for 25 years and is still a very long way from widespread adoption. It may well be another 25 years before the world is fully IPv6, and IPv4 will still exist for a long time come thereafter.

List of areas to be considered

Config entries

There are a couple of instances where a key is already used:

config show IPv6

We should use this as the basis for IPv6 settings.

IP addresses

I have no IPv6 from my provider so set up a 6to4 tunnel account with Hurricane:

https://tunnelbroker.net/

You can set up a free account and obtain a /64block

The following testing was done with a server in server only mode as this is the easier scenario.

My server is behind a Mikrotik router. I first set up the Mikrotik to handle the IPv6. Then I worked on the server.

The server will pick up an IPv6 address automatically from the tunnel via the router. It will need further configuration for SME to handle the tunnel instead of the router. However, this is sufficient for basic testing.

Remember that IPv6 address are public facing. I have not done any work on firewalling.

Some other brief thoughts:

  • Tunneled 6to4
  • Native IPv6 block from ISP
  • DHCP/DNS in Koozali
  • Routed using public IP and private address space?

Enable networking

  Warning:
Code below is highly experimental. TESTING ONLY. Do NOT try it on a production server as you will almost certainly get hacked


IPv6 currently disabled.

Get your Gateway IP "Server IPv6 Address:" and set it here:

IPv6=service
   status=enabled
   Gateway=2001:470:79c1:5ff::1

This seems to get it started:

mkdir -p /etc/e-smith/templates-custom/etc/sysctl.conf
nano /etc/e-smith/templates-custom/etc/sysctl.conf/net.ipv6
{
   if ( ($IPv6{status} || 'disabled') ne "enabled" ) {
       $OUT .= "# IPv6 is disabled\n";
       $OUT .= "net.ipv6.conf.all.disable_ipv6 = 1\n";
       $OUT .= "net.ipv6.conf.default.disable_ipv6 = 1\n";
   }
   else {
       $OUT .= "# IPv6 is enabled\n";
       $OUT .= "net.ipv6.conf.all.disable_ipv6 = 0\n";
       $OUT .= "net.ipv6.conf.default.disable_ipv6 = 0\n";
   }
}
mkdir -p /etc/e-smith/templates-custom/etc/sysconfig/network-scripts/ifcfg-ethX
nano /etc/e-smith/templates-custom/etc/sysconfig/network-scripts/ifcfg-ethX/60IPV6
{
if ($IPv6{'status'} eq "enabled") {
   $OUT .= "IPV6INIT=yes";
   $OUT .= "IPV6_AUTOCONF=yes";
   $OUT .= "IPV6_DEFROUTE=yes";
   $OUT .= "IPV6_PEERROUTES=yes";
   $OUT .= "IPV6_FAILURE_FATAL=yes";
   $OUT .= "DNS0=2001:4860:4860::8888"; # Google DNS - you may want to change them!!
   $OUT .= "IPV6_PRIVACY=no";
   } else {
   return "IPV6INIT=no";
}
mkdir -p /etc/e-smith/templates-custom/etc/sysconfig/network-scripts/route-ethX
nano /etc/e-smith/templates-custom/etc/sysconfig/network-scripts/route-ethX/08Gateway
{
   return "" unless (defined $GatewayIP && (
                       ($SystemMode eq 'serveronly' && $InternalInterface{Name} eq $THIS_DEVICE ) ||
                       ($ExternalInterface{Name} eq $THIS_DEVICE) ));
   $OUT .= "$GatewayIP dev $THIS_DEVICE\n";
   $OUT .= "default via $GatewayIP dev $THIS_DEVICE\n";
   if ($IPv6{'status'} eq "enabled") {
       $OUT .= "$IPv6{'Gateway' dev $THIS_DEVICE\n";
       $OUT .= "default via $IPv6{'Gateway'} dev $THIS_DEVICE\n";
   }
}


  Warning:
If you run the following command your server will have a public IP and NO firewall. You have been warned


signal-event post-upgrade;signal-event reboot.

You should get an automatic IP assigned from your Hurricane pool.

ip addr show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
   link/ether ca:94:35:c2:d6:e1 brd ff:ff:ff:ff:ff:ff
   inet 192.168.10.212/24 brd 192.168.10.255 scope global eth0
      valid_lft forever preferred_lft forever
   inet6 2001:470:79c1:5ff:c894:35ff:fec2:d6e1/64 scope global mngtmpaddr dynamic 
      valid_lft 2591951sec preferred_lft 604751sec
   inet6 fe80::c894:35ff:fec2:d6e1/64 scope link 
      valid_lft forever preferred_lft forever

Try a ping6

ping6 ipv6.google.com
PING ipv6.google.com(mad06s10-in-x0e.1e100.net (2a00:1450:4003:808::200e)) 56 data bytes
64 bytes from mad06s10-in-x0e.1e100.net (2a00:1450:4003:808::200e): icmp_seq=1 ttl=117 time=56.2 ms
64 bytes from mad06s10-in-x0e.1e100.net (2a00:1450:4003:808::200e): icmp_seq=2 ttl=117 time=55.5 ms


See the bug for some more templates that we might be able to use.

Firewall

ip6tables

Server/Gateway

Routing

DNS/DHCPD

DNS (PiHole in a docker container?)


Services

List of other affected services and vague efforts to get IPv6 running for them.

httpd

email

smbd

mysql (already listens for tcp6/3313)

ntpd (already listens on udp6/123)

sshd as below

ldap as below

=====SSH===== (bad hack here so careful as this may open your server up to remote access)

mkdir /etc/e-smith/templates-custom/etc/ssh/sshd_config
nano /etc/e-smith/templates-custom/etc/ssh/sshd_config/15ListenAddress
{
   my $access = $sshd{'access'} || 'private';
   my $address = ($access eq "public") ? "0.0.0.0" : "$LocalIP";
   # Not sure how we allow for 'Local IP only' with IPv6
   # Possibly limit it to the local subnet?
   if ($IPv6{status} eq "enabled") { 
       $OUT .= "ListenAddress ::\n";
       $OUT .= "ListenAddress $address\n";
   } else {
       $OUT .= "ListenAddress $address\n";
   }
}
signal-event remoteaccess-update

Then try:

ssh root@2001:470:1f13:3ff:2a9:b700:fe99:792c
LDAP
mkdir -p /etc/e-smith/templates-custom/etc/sysconfig/slapd
nano /etc/e-smith/templates-custom/etc/sysconfig/slapd/40OPTIONS

Add this code:

{
{
# Any custom options
#SLAPD_OPTIONS=" -4 -d { $ldap{LogLevel} || 256 } -s 0 "
my $slapdOptions = "#Test";
my $logLevel = $ldap{LogLevel} || 256;
if ($IPv6{'status'} eq "enabled") {
    $slapdOptions = "SLAPD_OPTIONS=\"-d  $logLevel -s 0\" " ;
    } else {
    $slapdOptions = "SLAPD_OPTIONS=\"-4 -d $logLevel -s 0\" " ;
}
$OUT .= "# Any custom options\n";
$OUT .= "$slapdOptions\n";
}

Edited the unit file /usr/lib/systemd/system/ldap.service to comment out the Environment line and just leave the config file

#Environment="SLAPD_URLS=ldap:/// ldaps:/// ldapi:///" "SLAPD_OPTIONS=-4 -d 256 -s 0"
EnvironmentFile=/etc/sysconfig/slapd
systemctl daemon-reload
systemctl restart ldap.service

However, /usr/sbin/cpu is not IPv6 aware and is unmaintained.

We can bypass this and force IPv4 by editing:

/etc/cpu-system.conf

Modify the template and change localhost to 127.0.0.1

[LDAP]
LDAP_HOST       = 127.0.0.1
LDAP_PORT       = 389

Other notes

Use in a web browser

https://[2001:470:1f13:3ff:2a9:b700:fe99:792c]

Ping

ping6 2001:470:1f13:3ff:2a9:b700:fe99:792c

Bugs

https://bugs.koozali.org/show_bug.cgi?id=6393