changeset 279:e36b7f4f85f2

Start to support IPv6 servers * Assumed only one or the other, not dual stack * Removed old VPS setup * Removed "secondary IP", added IPv4-to-6 forwarding * Updated firewall rules * Moved HTTP firewall rules to website module so it can do the right thing based on IP address families
author IBBoard <dev@ibboard.co.uk>
date Sat, 15 Feb 2020 13:52:30 +0000
parents a8bf3a400712
children 8f33f0bddd39
files manifests/nodes.pp manifests/templates.pp modules/my_fw/manifests/init.pp modules/my_fw/manifests/pre.pp modules/website/manifests/init.pp
diffstat 5 files changed, 109 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/manifests/nodes.pp	Sat Feb 15 13:12:44 2020 +0000
+++ b/manifests/nodes.pp	Sat Feb 15 13:52:30 2020 +0000
@@ -1,23 +1,6 @@
-
-node 'cloud.ibboard.co.uk' {
-	class { 'ibboardvpsnode':
-		primary_ip => '207.210.203.162',
-		secondary_ip => '143.95.92.165',
-		mailserver => 'mail.ibboard.co.uk',
-		imapserver => 'imap.ibboard.co.uk',
-		firewall_cmd => 'apf',
-	}
-	cron { 'apf-refresh':
-		command => '/etc/apf/apf --refresh >> /dev/null 2>&1 &',
-		hour => '*/6',
-		minute => '45'
-	}
-}
-
 node 'clouduk.ibboard.co.uk' {
 	class { 'ibboardvpsnode':
 		primary_ip => '213.229.111.243',
-		secondary_ip => '213.229.111.243',
 		mailserver => 'mail.ibboard.co.uk',
 		imapserver => 'imap.ibboard.co.uk',
 		firewall_cmd => 'iptables',
@@ -27,7 +10,6 @@
 node 'cloudtest.ibboard.co.uk' {
 	class { 'ibboardvpsnode':
 		primary_ip => '192.168.1.78',
-		secondary_ip => '192.168.1.78',
 		mailserver => 'mail.ibboard.co.uk',
 		imapserver => 'imap.ibboard.co.uk',
 		firewall_cmd => 'iptables',
@@ -36,6 +18,8 @@
 node 'ibbvps.vs.mythic-beasts.com' {
 	class { 'ibboardvpsnode':
 		primary_ip => '2a00:1098:82:52::1',
+		proxy_6to4_ip => '2a00:1098:82:52::01:d4', # ::old4 for IPv4!
+		proxy_upstream => ['2a00:1098::80:1000:3b:1:1', '2a00:1098::82:1000:3b:1:1' ],
 		mailserver => 'mail.ibboard.co.uk',
 		imapserver => 'imap.ibboard.co.uk',
 		firewall_cmd => 'iptables',
@@ -46,4 +30,10 @@
 		ensure => 'running',
 		enable => 'true',
 	}
+	firewall { '090 Allow SSH (IPv4-to-IPv6)':
+		dport => 22,
+		source => '2a00:1098:0:82:1000:0:5d5d:826a',
+		proto => 'tcp',
+		action => 'accept',
+	}
 }
--- a/manifests/templates.pp	Sat Feb 15 13:12:44 2020 +0000
+++ b/manifests/templates.pp	Sat Feb 15 13:52:30 2020 +0000
@@ -27,14 +27,17 @@
 
 class basevpsnode (
 	$primary_ip,
-	$secondary_ip,
+	$proxy_6to4_ip = undef,
+	$proxy_upstream = undef,
 	$mailserver,
 	$imapserver,
 	$firewall_cmd = 'iptables',
 	) {
 
 	if $firewall_cmd == 'iptables' {
-		include vpsfirewall
+		class { 'vpsfirewall':
+			fw_protocol => $primary_ip =~ Stdlib::IP::Address::V6 ? { true => 'IPv6', default => 'IPv4'},
+		}
 	}
 
 	#VPS is a self-mastered Puppet machine, so bodge a Hosts file
@@ -53,7 +56,8 @@
 	include vcs::client
 	class { 'webserver':
 		primary_ip => $primary_ip,
-		secondary_ip => $secondary_ip,
+		proxy_6to4_ip => $proxy_6to4_ip,
+		proxy_upstream => $proxy_upstream,
 	}
 	include cronjobs
 	include logrotate
@@ -69,12 +73,16 @@
 
 ## Classes to allow facet behaviour using preconfigured setups of classes
 
-class vpsfirewall {
+class vpsfirewall ($fw_protocol) {
 	resources { "firewall":
 		purge => false,
 	}
-	firewallchain { 'INPUT:filter:IPv4':
-		purge => true,		
+	class { "my_fw":
+		ip_version => $fw_protocol,
+	}
+	# Control what does and doesn't get pruned in the main filter chain
+	firewallchain { "INPUT:filter:$fw_protocol":
+		purge => true,
 		ignore => [
 			'-j f2b-[^ ]+$',
 			'^(:|-A )f2b-',
@@ -82,61 +90,52 @@
 			'--comment "Do not purge',
 			],
 	}
-	Firewall {
-		before => Class['my_fw::post'],
-		require => Class['my_fw::pre'],
-	}
-	class { ['my_fw::pre', 'my_fw::post']: }
-	class { 'firewall': }
-	firewall { '010 Whitelist Googlebot':
-		source => '66.249.64.0/19',
-		dport => [80,443],
-		proto => tcp,
-		action => accept,
-	}
-	# Block a spammer hitting our contact forms (also on StopForumSpam list A LOT)
-	firewall { '099 Blacklist spammers 1':
-		source => '107.181.78.172',
-		dport => [80, 443],
-		proto => tcp,
-		action => 'reject',
+	if ($fw_protocol != "IPv6") {
+		firewall { '010 Whitelist Googlebot':
+			source => '66.249.64.0/19',
+			dport => [80,443],
+			proto => tcp,
+			action => accept,
+		}
+		# Block a spammer hitting our contact forms (also on StopForumSpam list A LOT)
+		firewall { '099 Blacklist spammers 1':
+			source => '107.181.78.172',
+			dport => [80, 443],
+			proto => tcp,
+			action => 'reject',
+		}
+		firewall { '099 Blacklist IODC bot':
+			# IODC bot makes too many bad requests, and contact form is broken
+			# They don't publish a robots.txt name, so firewall it!
+			source => '86.153.145.149',
+			dport => [ 80, 443 ],
+			proto => tcp,
+			action => 'reject',
+		}
+		firewall { '099 Blacklist Baidu Brazil':
+			#Baidu got a Brazilian netblock and are hitting us hard
+			#Baidu doesn't honour "crawl-delay" in robots.txt
+			#Baidu gets firewalled
+			source => '131.161.8.0/22',
+			dport => [ 80, 443 ],
+			proto => tcp,
+			action => 'reject',
+		}
 	}
-	firewall { '099 Blacklist IODC bot':
-		# IODC bot makes too many bad requests, and contact form is broken
-		# They don't publish a robots.txt name, so firewall it!
-		source => '86.153.145.149',
-		dport => [ 80, 443 ],
-		proto => tcp,
-		action => 'reject',
-	}
-	firewall { '099 Blacklist Baidu Brazil':
-		#Baidu got a Brazilian netblock and are hitting us hard
-		#Baidu doesn't honour "crawl-delay" in robots.txt
-		#Baidu gets firewalled
-		source => '131.161.8.0/22',
-		dport => [ 80, 443 ],
-		proto => tcp,
-		action => 'reject',
-	}
-	firewallchain { 'GREATFIREWALLOFCHINA:filter:IPv4':
+	firewallchain { "GREATFIREWALLOFCHINA:filter:$fw_protocol":
 		ensure => present,
 	}
 	firewall { '050 Check our Great Firewall Against China':
 		chain => 'INPUT',
 		jump => 'GREATFIREWALLOFCHINA',
 	}
-	firewallchain { 'Fail2Ban:filter:IPv4':
+	firewallchain { "Fail2Ban:filter:$fw_protocol":
 		ensure => present,
 	}
 	firewall { '060 Check Fail2Ban':
 		chain => 'INPUT',
 		jump => 'Fail2Ban',
 	}
-	firewall { '100 allow https and http':
-		dport => [80, 443],
-		proto => tcp,
-		action => accept,
-	}
 	firewall { '101 allow SMTP':
 		dport => [25, 465],
 		proto => tcp,
@@ -411,13 +410,15 @@
 #Our web server with our configs, not just a stock one
 class webserver (
 	$primary_ip,
-	$secondary_ip,
+	$proxy_6to4_ip = undef,
+	$proxy_upstream = undef,
 	) {
 	#Setup base website parameters
 	class { 'website':
 		base_dir => '/srv/sites',
 		primary_ip => $primary_ip,
-		secondary_ip => $secondary_ip,
+		proxy_6to4_ip => $proxy_6to4_ip,
+		proxy_upstream => $proxy_upstream,
 		default_owner => $defaultusers::default_user,
 		default_group => $defaultusers::default_user,
 		default_tld => 'co.uk',
@@ -516,14 +517,16 @@
 
 class ibboardvpsnode (
 	$primary_ip,
-	$secondary_ip = $primary_ip,
+	$proxy_6to4_ip = undef,
+	$proxy_upstream = undef,
 	$mailserver,
 	$imapserver,
 	$firewall_cmd = 'iptables',
 	){
 	class { 'basevpsnode':
 		primary_ip => $primary_ip,
-		secondary_ip => $secondary_ip,
+		proxy_6to4_ip => $proxy_6to4_ip,
+		proxy_upstream => $proxy_upstream,
 		mailserver => $mailserver,
 		imapserver => $imapserver,
 		firewall_cmd => $firewall_cmd,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/my_fw/manifests/init.pp	Sat Feb 15 13:52:30 2020 +0000
@@ -0,0 +1,10 @@
+class my_fw ($ip_version) {
+  Firewall <| |> {
+    provider => $ip_version == "IPv6" ? { true => 'ip6tables', default => 'iptables'},
+  }
+  class { ['my_fw::pre', 'my_fw::post']: }
+  class { 'firewall':
+    ensure => $ip_version == "IPv6" ? { true => 'stopped', default => 'running'},
+    ensure_v6 => $ip_version == "IPv6" ? { true => 'running', default => 'stopped'},
+  }
+}
\ No newline at end of file
--- a/modules/my_fw/manifests/pre.pp	Sat Feb 15 13:12:44 2020 +0000
+++ b/modules/my_fw/manifests/pre.pp	Sat Feb 15 13:52:30 2020 +0000
@@ -2,9 +2,13 @@
   Firewall {
     require => undef,
   }
+
+  $icmp_proto = $my_fw::ip_version == "IPv6" ? { true => 'ipv6-icmp', default => 'icmp' }
+  $localhost = $my_fw::ip_version == "IPv6" ? { true => '::1/128', default => '127.0.0.0/8' }
+
    # Default firewall rules
   firewall { '000 accept all icmp':
-    proto   => 'icmp',
+    proto   => $icmp_proto,
     action  => 'accept',
   } ->
   firewall { '001 accept all to lo interface':
@@ -15,7 +19,7 @@
   firewall { "002 reject local traffic not on loopback interface":
     iniface     => '! lo',
     proto       => 'all',
-    destination => '127.0.0.1/8',
+    destination => $localhost,
     action      => 'reject',
   } ->
   firewall { '003 accept related established rules':
--- a/modules/website/manifests/init.pp	Sat Feb 15 13:12:44 2020 +0000
+++ b/modules/website/manifests/init.pp	Sat Feb 15 13:52:30 2020 +0000
@@ -1,8 +1,9 @@
 class website(
   Pattern[/^(\/[^\/]+)*$/] $base_dir,
   Pattern[/^(\/[^\/]+)*$/] $cert_dir           = '/etc/pki/custom',
-  String $primary_ip,
-  String $secondary_ip,
+  Stdlib::IP::Address $primary_ip,
+  Stdlib::IP::Address::V6 $proxy_6to4_ip = undef,
+  Array[Stdlib::IP::Address::V6]  $proxy_upstream = undef,
   String $default_owner,
   String $default_group,
   String $default_tld        = 'com',
@@ -118,6 +119,33 @@
   file { $cert_dir:
     ensure => directory;
   }
+  firewall { '100 allow https and http':
+    destination => $primary_ip,
+    dport => [80, 443],
+    proto => tcp,
+    action => accept,
+  }
+  if ($proxy_6to4_ip != undef) and ($proxy_upstream != undef) {
+    augeas {'/etc/sysconfig/network-scripts/ifcfg-eth0':
+      context => "/files/etc/sysconfig/network-scripts/ifcfg-eth0",
+      changes => "set IPV6ADDR_SECONDARIES $proxy_6to4_ip",
+    }
+    $proxy_upstream.each |String $upstream_addr| {
+      firewall { "100 limit PROXY protocol to upstream $upstream_addr":
+        source => $upstream_addr,
+        destination => $proxy_6to4_ip,
+        dport => [80, 443],
+        proto => tcp,
+        action => accept,
+      }
+    }
+    firewall { "101 block all other PROXY protocol access":
+      destination => $proxy_6to4_ip,
+      dport => [80, 443],
+      proto => tcp,
+      action => reject,
+    }
+  }
   if $operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '7') >= 0 {
     exec { 'set_apache_defaults':
       command => 'semanage fcontext -a -t httpd_sys_content_t "/srv/sites(/.*)?"',