summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--certs/ipsec/antilop.pem32
-rw-r--r--certs/ipsec/benjamin.pem32
-rw-r--r--certs/ipsec/civett.pem31
-rw-r--r--certs/ipsec/elefant.pem32
-rw-r--r--certs/ipsec/giraff.pem31
-rw-r--r--certs/ipsec/mistral.pem32
-rw-r--r--group_vars/all.yml15
-rw-r--r--production8
-rw-r--r--roles/common/files/etc/logcheck/ignore.d.server/strongswan-local19
-rw-r--r--roles/common/files/etc/strongswan.d/charon.conf303
-rw-r--r--roles/common/files/etc/strongswan.d/charon/socket-default.conf20
-rwxr-xr-xroles/common/files/usr/local/sbin/update-firewall.sh102
-rw-r--r--roles/common/handlers/main.yml6
-rw-r--r--roles/common/tasks/ipsec.yml96
-rw-r--r--roles/common/tasks/logging.yml1
-rw-r--r--roles/common/tasks/main.yml5
-rw-r--r--roles/common/templates/etc/fail2ban/jail.local.j22
-rw-r--r--roles/common/templates/etc/ipsec.conf.j243
-rw-r--r--roles/common/templates/etc/ipsec.secrets.j25
-rw-r--r--roles/common/templates/etc/iptables/services.j27
-rwxr-xr-xroles/common/templates/etc/network/if-up.d/ipsec.j247
21 files changed, 798 insertions, 71 deletions
diff --git a/certs/ipsec/antilop.pem b/certs/ipsec/antilop.pem
new file mode 100644
index 0000000..cdb3809
--- /dev/null
+++ b/certs/ipsec/antilop.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFbjCCA1agAwIBAgIJAK1L1Q45QyGyMA0GCSqGSIb3DQEBDQUAMEcxEDAOBgNV
+BAoMB0ZyaXBvc3QxETAPBgNVBAsMCFNTTGNlcnRzMQ4wDAYDVQQLDAVJUFNlYzEQ
+MA4GA1UEAwwHYW50aWxvcDAeFw0xNjA1MjExMzIwMjBaFw0yNjA1MTkxMzIwMjBa
+MEcxEDAOBgNVBAoMB0ZyaXBvc3QxETAPBgNVBAsMCFNTTGNlcnRzMQ4wDAYDVQQL
+DAVJUFNlYzEQMA4GA1UEAwwHYW50aWxvcDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAPZCYTbXuTseBaYueoPorgtGGUe6/e3j5SStzCwb4flNniqqVoCq
+JXxSg72IAmwTrsnUwWx/iNm/g7N15/509rW5mE+YXksoDYORig32F9TtVEinUuHz
+EDh+nYis/YzoOM1ErdDpQL880ydskTaqvKKLGdigaosvFUJMUYhqYPnw1opQIH5r
+6YRqTz9l8GThuA+6Ujb7mlvSv6Pk4pMcRNb3cnDoDD2YJ0U0gOXah6Sw9VEFmh/U
+bv0eietvLTy1RvqiC/I6IpR1kZb5jtTo5EHkXqc2hyDNppAWW59YmIoJNIFuC8/Q
+nFM2d9JIP6RGY0bu5TaYmM4xpnSzgX0dIQ9ysZXP8uqZj/StaONtohxxpqnUiT+X
+hQQdX2sW4/6vAyl5m6ukXqKPwapOuQN2ZDDRHWq68qoPu5w+b9AlKHUnpbxNh6JO
+6M3e09TPg/+uQ8OBw37fRixIvfZlpWeGy513l1NKlnJwkjiR8jmnsbMQ8yKLrXbH
+JXAXHI8J681JALVm1hi1uwr8N58Tg/L1MRpG1vIT9rmdNsUZWEWSmEt6FLWgKs5J
+bMIx4jILrvxxaGOa40G7JuKiaKN7u5RqRm3IBWeoNPQN+axZj2pe3n2AqMZP8a5p
+dYPz0mzE7xTCS++kYcmwHJwlylRbRGmAFHb22T/lnSR4WdaxcShnBI8hAgMBAAGj
+XTBbMBwGA1UdEQQVMBOBEWFkbWluQGZyaXBvc3Qub3JnMAwGA1UdEwEB/wQCMAAw
+DgYDVR0PAQH/BAQDAgKkMB0GA1UdDgQWBBQlgc0BvZLpfrqs9jXqUXVxMxYNlzAN
+BgkqhkiG9w0BAQ0FAAOCAgEAIJ85xKCU/s4EbcodFL6walMLsaXKnEHo0oY29EUv
+bGl+1qzlWuedwXti5ND+6a5iO8RMHtexOoQ+GTUBv/wMGgiElvkvtT9FsFxijnh3
+D4a3TqFQTVRTUuJVP/uULe18eScAyWVdArL1NJHDz/GoHjtUdzfCVKgTMNWIx4yC
+E5i3IGJsGDAFLl19N5if+TfGjj90QkH1TzC4jOF6Y3oxkY4ZVwLtb0E/uR/zk8HI
+9wF7lw2/5J+aqyyaWnsd66fzJGk/3lELWJbOvXN6KbS3YcWOhXrOV7ijdZRyaHWo
+jB7nWRjLfb8KUSNXnzq4/8Zs3ka6WeBDB1pd4glcKeaMOdm5K/NspsS8ziGWHeoQ
+XlFFxP/Msw5NlUvlSjZ3qZzNg4550Ci/FweBavGihSCakmkZMvq7Kvg67j6mStZS
+Qm5t+sVTiJ036+m1TcUpfRJ9VPkYFhA25Bk+XKctxTu2Hcs2P9Q60oO3BGkTIoPQ
+uKjE/HtTuLb7RtaMtUs8K1j9Pq9j9F271EAOb7JzQlhEt0w+QQyoiQVPOD0RZ6T3
+LAzXz0qX0fEk2DOf6jCjNJg4TJaWzLaVo4lkTv4dcYSvZlZnDwSX6h/LoizP6zYK
+voqUuBt9+hksXPenDT/lCaYv2w+C4NdzsH4FQ5FUNPVqGdyqA9pynDxrjELkTaNp
+DZw=
+-----END CERTIFICATE-----
diff --git a/certs/ipsec/benjamin.pem b/certs/ipsec/benjamin.pem
new file mode 100644
index 0000000..57c9052
--- /dev/null
+++ b/certs/ipsec/benjamin.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFcDCCA1igAwIBAgIJAJkbw4unO7z/MA0GCSqGSIb3DQEBDQUAMEgxEDAOBgNV
+BAoMB0ZyaXBvc3QxETAPBgNVBAsMCFNTTGNlcnRzMQ4wDAYDVQQLDAVJUFNlYzER
+MA8GA1UEAwwIYmVuamFtaW4wHhcNMTYwNTIxMTMyMTIwWhcNMjYwNTE5MTMyMTIw
+WjBIMRAwDgYDVQQKDAdGcmlwb3N0MREwDwYDVQQLDAhTU0xjZXJ0czEOMAwGA1UE
+CwwFSVBTZWMxETAPBgNVBAMMCGJlbmphbWluMIICIjANBgkqhkiG9w0BAQEFAAOC
+Ag8AMIICCgKCAgEAwOODNQ5sdVXFrzAeo9bChbauUP69uXoc6OP/l1xB9kjzmErE
+noAlVjKO05nUE6Uus03/RkEPdyaMCfKarAhbFHaowtylUjUcIsVJkGsem4vRtuLv
+929vLx4TdL8BN5NCMsXOecoI5z//lfJ4YVfpmLQ+OUM8kWNcHOPRpnLLZq/Pwvn9
+3WbzWmxlcmVZUwq66f0N9zBSk8678TikZGx2dJ/HZwigswo0PSxTIbvE2eoDdFoh
+i9RrBxpXTnsxCAXpFIV7SLobw+tQvuv+r2oK5oGOnHIGmJZWVC3bRIb+PPELeB1g
+3TfNz7bP5PRKpXnP0cdK/0J2A+vQqArr8ACsgzxsKUb7t9OASLH14fQ25FJ3nsc+
+CS9snXIxJourd5d2cyhMe3xBo0tzPLC8sc3mwIyuz60o0pOjvIfzlYyldtYk3CTC
+VKMs1UpLnea8DDIvzhWn+TLX2yAKS/KNG0Tw72aLc86ZUVKV0+fkwjRWtIAWSJQZ
+L/tOl4iDyU+T9dG9dDR1KlsfW0JBGTkyZOLZrSBVQvDj/aUQjgc8e54MghJsS5Qd
+AvD2rTO5liqB8YzHY77Nj2d4f5kqBHj41KwtGOQT4nXYI+rdOpkmkMj5kOGoeRIC
+Sv+eszXADnHHtoPS73rjej0gseibSvvm9n3iKkd5mm2N2oZ9Q5pF52CUFfMCAwEA
+AaNdMFswHAYDVR0RBBUwE4ERYWRtaW5AZnJpcG9zdC5vcmcwDAYDVR0TAQH/BAIw
+ADAOBgNVHQ8BAf8EBAMCAqQwHQYDVR0OBBYEFEDI1UY3Ng7TSEMllOYaasPL05JK
+MA0GCSqGSIb3DQEBDQUAA4ICAQCy/YSxqCu6r4H0+XPdoz9TYoIkW3V4f7nupw09
+q6Zhpnl4T5a7WJnY/6Pda9Y+4f1+uR1OMJ+kgH4K6RyCjzobgjEGpVlxBpmA/8Q/
+634zc1cUna/sa7Jd/taTnqTZRbT7C9aZyIkJoN0Cco/k8QI6gvsMmGDh37nS6keB
+opy5XBTVEcysH8JPVlVFwGm+FL7n45GM7A4ju6wujeyAJ9I7IxFJM5d8B5r6zt5L
+MAdMYdPDR6TRyKcmEbsb0Jq+dI8kQFRr0IApIb8m+Z3O0AyBqtdGX+EQIoXijGH0
+NRPN6YKPU1U0Ha2ti3VRalVSHuvk+/kBYNeCZA3DB0QT9obLOj/CrOMutfXtsNUU
+eG7x+L/sjHnVSaKOQ5rtAcoF1GrqAGnmZTN0H9IbAG8/WU9pefNHQt7V5+5xtDmA
+ywMHqRgYQKTD4CRhmGgqcHEr6ls7rhI7YbAoTgwbUMe9kHdVFiE3ZutYSkWln5E0
+Jc/K6LXo0kiwMgsEG98qNzlNRHsvp+UHuKaiuBD28HwLxGo1M5rp3MItm9FoMPpm
+tUcEp2/6RJLrSZNLU6Lx9ZF3HIj0e42e+laIfu46o8ZEIsvwac3iZN/nonxTGaoy
+n4W1AW/F8cXpO0YG7xtyHyTL+d/1WmurpXKgKmE+0mOMeAJjQn9G4aUl+/UkPlGb
+V/aK7w==
+-----END CERTIFICATE-----
diff --git a/certs/ipsec/civett.pem b/certs/ipsec/civett.pem
new file mode 100644
index 0000000..d0de31f
--- /dev/null
+++ b/certs/ipsec/civett.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIJAN3ZQpjOL9/yMA0GCSqGSIb3DQEBDQUAMEYxEDAOBgNV
+BAoMB0ZyaXBvc3QxETAPBgNVBAsMCFNTTGNlcnRzMQ4wDAYDVQQLDAVJUFNlYzEP
+MA0GA1UEAwwGY2l2ZXR0MB4XDTE2MDUyMTEzMjE1NVoXDTI2MDUxOTEzMjE1NVow
+RjEQMA4GA1UECgwHRnJpcG9zdDERMA8GA1UECwwIU1NMY2VydHMxDjAMBgNVBAsM
+BUlQU2VjMQ8wDQYDVQQDDAZjaXZldHQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDmnVdJXUgGbvTIH9jKK+eIHOkaJMAcC+lXLFAMee9t7YVsyrpmCdt4
+fVTQJFBwp9GiW1Y+dqBQBWvr9z6l/m68CsZOJoJ5Telmcv42tpoDtf0eEANo17/D
+VRbQHJzJmAZQ7OkyPGFSKQy9XUqLq1+OkM+zRuy8TvnUa0mLdHR5ykEJl0P541mW
+yn1LMQON5cRzVMHwTmDSnPhzn+7YQU2sHpHKJaLVPq+yXaN1JoUglySIjlquk6Ji
+paAwMer8CHXnnjoQw+L6/bsZCc02Zz96M/CDqlow88Ut6o6qFR6L3B8go3qgSbbU
+ERB4n9KcyUyhwp+joIE1J2TkEfguumVYrS/j00pHKz1Iug9z0HqXKesWEOwy0f9C
+AbdpEnmk7+3nU8zJVVqmJjbdB2OS4Cy3R0jeNNu4P581NxEktETCSl3+bwAhvTN0
+QAs3mWNLuVEREoPGQr3sUq9kRfKah09VVgSHsQutf6/7A5oNd8zx48Ff3Mn7miS6
+aDbuWPLjCdRYczBO3y2PBQeZDANqa3SSTZvQgRFXnkey1Em1UtMIB3KCTYTuPU7G
+jlm2q+T/f2yL5K3zNrF+6X8HIrFb6xIkoYy6SCNYH2S4bXsRI3KlCFH+mIHuQJg8
+hVTlNOABfOoM9ZXmt+9zkWcy4QQiUA6Rbrtu7JOg34PorIm6XYUANQIDAQABo10w
+WzAcBgNVHREEFTATgRFhZG1pbkBmcmlwb3N0Lm9yZzAMBgNVHRMBAf8EAjAAMA4G
+A1UdDwEB/wQEAwICpDAdBgNVHQ4EFgQUjtpNnjSQRjO6regLVnpSvcnBaxUwDQYJ
+KoZIhvcNAQENBQADggIBAOZgyZp5le0PLCzMU1Qp96jfPUF0u/hdScQ9EVRzXjGT
+S6qhrEv5XYOCxU4XBzika071FaYo8OrEV3oq+Y7MtdQbK3pMKhN7ilSiX/dYFM3t
+cUEHwZ14e5OJ0NZfyWXk0GvGNURqn7r/AZWrfGn+uSe+ndxAZuV363NxQYPVbtTi
+dK81lkyue3CwSGdGh3BgyRrQ86JWvcjpFaCQeOENUtwlBfGDNEwtQ7I52NIEKxpX
+3pDvE0/x14JSx9pO3BXK6SH1zt/8bXiW9A8XEkMoVsAOL1ntrzCCLPM6mP2JEoDD
+vAEr360T5T4cTTym+4Or3gPm9RMwEfca3ZHzZkxUXChKn+YZ4r9kpWVgIxoIGZdd
+ZeoA/oO2feLPHM4whBP6x4tyceoqLyA11Gaj5JKtLJTGIb+1zjni8IVuINuWN/YD
+ZOfn+lGsL/qft2hQ/UopSXDcnVj+dxPdcWaUCfTN3oOqLDSTmcR2bbLmVDL8oMef
+pZlaSIJ6p4dGQAs4lwvROE8WTb6b21rNZy7O4Po2jpH5fhHsxgqEByvloYenaadV
+Oian0DfuKXdI7K4v1kq6UfRRwR3LzNnE9Gy9aeSKyCFZhg67CAeKgt6i5VmgrDGw
+rbIpPky5FUpUHkA1WMxP1Wl1ZESZRVLV2A1rUD4gzZiVV3cEM85r98GSogBleXR7
+-----END CERTIFICATE-----
diff --git a/certs/ipsec/elefant.pem b/certs/ipsec/elefant.pem
new file mode 100644
index 0000000..25561ae
--- /dev/null
+++ b/certs/ipsec/elefant.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFbjCCA1agAwIBAgIJAO+HSCLdxxt9MA0GCSqGSIb3DQEBDQUAMEcxEDAOBgNV
+BAoMB0ZyaXBvc3QxETAPBgNVBAsMCFNTTGNlcnRzMQ4wDAYDVQQLDAVJUFNlYzEQ
+MA4GA1UEAwwHZWxlZmFudDAeFw0xNjA1MjExMzIyMjFaFw0yNjA1MTkxMzIyMjFa
+MEcxEDAOBgNVBAoMB0ZyaXBvc3QxETAPBgNVBAsMCFNTTGNlcnRzMQ4wDAYDVQQL
+DAVJUFNlYzEQMA4GA1UEAwwHZWxlZmFudDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBALYLJRUZlY4xnWOJgaUsv9FDkTcTU2FtxMw4QHEL1lBRwl8gWx0O
+2bAfF4Jm9lGEMTjryDrMbx3YfonZ+jC7ZEisPNjuP7VpUgI9VIeN0L0W1f8ROvvB
+ByuRhC+1qitK1uU60jSQ+MdhkGeXz22d6xkthJi9v7ppx62rLlzQaS+GdumOuyvj
+hG3f+Mcw8u0Lw/stZ+PDEiG33DF/iDKWJvxq53SFk22BAsvpE1NfmY4RYZOz2qPK
+JGX2t6HPwwVW93vUKavAgYW2Tpy0iOoBi2zDU90md879Ttsju833NMk6g/RcrY15
+UsGep23LcXw/TGTzZa1Fsi8LxzfBwuTljmEye16j30HALxY7x68PmaPbER3WJy7A
+gvO3QuHKzU8fyTrTCBysCRlEnt37r0LyiAHeoaV3Ij5lXAG/2F5iJHLpW5Gv8uM9
+2wHjTCNTSF3L25rsKHUvNUbO9OcYCVXS2wEiysY/UEqOHW2C2auUmh+I0bbpYjjZ
+Xq/7KeGx43fdnmsG3W+KYtkZr4bvxZkscPAKvIMUx0DL/gjBA7Pv2BgMrF5XSxCj
+moFU8QSp/W4HWvajkwdZOR7dn1WWFL81Ctvbb4ago6u48AY6a4FHP3kbThDyQKDi
+8mL/YU35CiufgPX7N0k/pLYDViyRnC+WOi8Me5CPzZQSj7wtliyvGRKHAgMBAAGj
+XTBbMBwGA1UdEQQVMBOBEWFkbWluQGZyaXBvc3Qub3JnMAwGA1UdEwEB/wQCMAAw
+DgYDVR0PAQH/BAQDAgKkMB0GA1UdDgQWBBQ6/gMd6OCGn7QXO073QppLV5GfJDAN
+BgkqhkiG9w0BAQ0FAAOCAgEAVUOkssSdKXMP95GcnbIeGCCcZ3/mieYfOHZ4ndPV
+BaGd/4hmey29YNszRaAbAUOvdvnWHl3lcfgeu7H+qzKX/RpWnliL1CvtxNQ8ePor
+dNYpr6ah0MTwiP2dfxX6tLyH+rGaADz6IkeFZ/ZKO7CPcxfedjmY7Snk4mCDVmbZ
+XkDd1EkGePF6zU5wy/TRrckmoUm2cL2wXLv7hvIcDvKYta02+WspdRtKciw2RcNE
+2igIfTt69U6U4e5+g4jXTW3gI8wM2xjr1NDrzTTE8519mmpsfrQeOBHKOJgWjJWJ
+PjSwuaYrUIlYqB4mqL2BhakIuuH8P8Z68F9qelICiiSMGZu4wvZpIEDetaB0NlWP
+u5YE8kG/xD85p1bFC9H5/e7f8LKQz/ZxpazsKlUvMB0q4WBpTcoBrjnfjprLOjf8
+aeJ0kcAUSy8pR49rq7k9j8+onDqGoVV9mzAH9hzD1itU0hHKEB0uKH48XMRBhnUn
+ViXQZHRDuYDuUbvvKzss/Ul85S2OGwKWKUhOocFtDj57p38yCgbhffm31ja/N3Td
+hPLDA9u9oIL6Hh5GzDGdx7z4MoV1eTAQqCK/rk7XVHyt9hb1ADRETLT2NlgovkQq
+TFlHZ/9hCGAW8IcqzTDA4yCJ3XHZ8WLaUr9t3Rr7mUUnIB9cRJoZd3lkt/2bdvEI
+OHI=
+-----END CERTIFICATE-----
diff --git a/certs/ipsec/giraff.pem b/certs/ipsec/giraff.pem
new file mode 100644
index 0000000..1abb655
--- /dev/null
+++ b/certs/ipsec/giraff.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIJAJJw5lIqPzO2MA0GCSqGSIb3DQEBDQUAMEYxEDAOBgNV
+BAoMB0ZyaXBvc3QxETAPBgNVBAsMCFNTTGNlcnRzMQ4wDAYDVQQLDAVJUFNlYzEP
+MA0GA1UEAwwGZ2lyYWZmMB4XDTE2MDUyMTEzMjI0N1oXDTI2MDUxOTEzMjI0N1ow
+RjEQMA4GA1UECgwHRnJpcG9zdDERMA8GA1UECwwIU1NMY2VydHMxDjAMBgNVBAsM
+BUlQU2VjMQ8wDQYDVQQDDAZnaXJhZmYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDFN5v7clsY27jVOmh4kHMiPqcLSb7IEeYZNHnvRd1Vm6F/HRsniXCq
+dujue1aoLscVLQMeiQd2R0g0oLIue8DG7FaQreWFmAmUK7kwsocQYZwgzLMvOtmc
+0eGnG4B4xJjQTDTAuetv8zVJAoclJTxki3oOlyUKvoRU67q0hD93xguyKxxwGMnL
+4qbrLcf7BrwTF2khWOEOy/PaYQDWxDFtoG6Z/HtG+PmiLD0EPbawZ3iUPXWCmXz3
+lftK+D4vL74MYRc6uy10XYT2yY0Lo9wxtPh1a918IBOuD+fP89povs/BWhI2BYyY
+NplXJAzgkNz8zA/UmRuLcy6SoXx8YLsIaiDOL9bV3WzhdTXwQ17DqLY2SYktcp5i
+Q5uC5IRLCY7moCTOMjeg6RDXaIz9DsShT0SNpxuZx/XF5g6HV/CdKMjNzKojPuMX
+rBiVCIM/sp+r1p9rk7jDWy2sbS0TXOMFQf+scf2BZtFipoNZDhNZ3LfYg+HI9Zjo
+Ic4GqSXQ5kS1n7OXxrh7XZCo/PzjVRxtJGnQCFEBtuGT10jF1Il7c4QPJgOa/XI0
+4OZE+nHcSfZjFXo1+hlJYcE+IggRSW+UzmKxbZYMrfKfgf+zwuaL3EC2XgzBuUjr
+YptvXT+AtC2eThwvts4TmE7WBsGMqgIt5BPkrgqILD+c16ty4uBqlQIDAQABo10w
+WzAcBgNVHREEFTATgRFhZG1pbkBmcmlwb3N0Lm9yZzAMBgNVHRMBAf8EAjAAMA4G
+A1UdDwEB/wQEAwICpDAdBgNVHQ4EFgQUTdOW7rIhDPUoInZJ3KBO+tvvHMEwDQYJ
+KoZIhvcNAQENBQADggIBADpn7Cv7Ua6jcA3gDfWqyx9DXH8q213b8ZSTiGdkwQjh
+7DMM98u04cOKu/PLDQKbsW5IldZnd7vcPOowp40LlXoXWfmJFOHUtjmWzHieqLnn
+9uxwVgqx1vtCP+XXNEKHc0LlVsRze0LQJducjtrV8cIOd7nnXyXwr5dc4Cb+u3SB
+28gwuUSapdnCpTKKNoWgFeRAxQMaaV1v3lfkO4UKdT4bHNl+9b4BhOKCVB6ujgvC
+R+iUoz2MAaP62m6f4pIPq+ftlaZFCbss6O6aCgqyCtt+8bTJZoGmig3iDzvzMK6D
+lYf8i9rnTeBglBA7pcVzpmDFdMLIod6fpFnVpnun6fxyuS23ch9aJR4osuGVVLY/
+zasF7bbYHQJcggCTdK3ZdCnTV8BjEXBtzJ5b4pD4x+EBeohZ3gV57Wlyr2RHhu7s
+IIDC9yp5B32gFhq58rKQz81cMC21eX25OiRFuLSP6DDQAuJYP3ULEs0GiGnG1+ly
+pMTbXMwmQAr/GPQutGLqVgv8OqtxkBiPj0ntuucyjq5u+6AQz5v+4rc9gTbzYenU
+io9pHYZJ5FQWHs1ouy3BAJstvn2HkKBBJu2SA8PfNw3WFysK6ERKEMjtIl/KASze
+X/TgfTYkoaDqFtJdK1eRlipWiIqBbqb3A3h4XpiDIXg7QcdNLnT4I2AkBs2n9Nv6
+-----END CERTIFICATE-----
diff --git a/certs/ipsec/mistral.pem b/certs/ipsec/mistral.pem
new file mode 100644
index 0000000..5267b8e
--- /dev/null
+++ b/certs/ipsec/mistral.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFbjCCA1agAwIBAgIJAIUSa/zsUYWuMA0GCSqGSIb3DQEBDQUAMEcxEDAOBgNV
+BAoMB0ZyaXBvc3QxETAPBgNVBAsMCFNTTGNlcnRzMQ4wDAYDVQQLDAVJUFNlYzEQ
+MA4GA1UEAwwHbWlzdHJhbDAeFw0xNjA1MjExMzIzMDlaFw0yNjA1MTkxMzIzMDla
+MEcxEDAOBgNVBAoMB0ZyaXBvc3QxETAPBgNVBAsMCFNTTGNlcnRzMQ4wDAYDVQQL
+DAVJUFNlYzEQMA4GA1UEAwwHbWlzdHJhbDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBANHZ/qp0B3rFnhwHyXLXiLjrrDtfjTamYl/b0RSRv4DMQ3dml8hR
+jFjr6P4f/UJkIHev0g1MwOXEaH2QqMFBq7YNsCnEPyUdokNZ2MEk6RcaKzixLJZr
+hW1zQE6E44S3x1ZJzoqP2U4VA8nCKObIqsBcsciIBH8G2zTUz8oiNphUTn19XNq1
+K+wyqUX7O/ltq+ouUC/dQcLaS/CJIGAu9qqEZphou4W46kxXsApMgIY+9uD8bTCn
+tsRTtFdsEDDoL5tpZTndVRktavC2jV8DOTlSaX3QjlpParLFZR24KQUEJkjprixx
+xZ5Rbs7FhxCWjBd9PCS9aCr2dmjC5p9dQNFb5HOJTNkFQ5/UqmvKmOi95YPE+4LD
+4pN5w597L04yGVjokN+yanLpk91HNn3j4psMYgaHPRcefyZnZ64nNB5QZL8NVgGs
+L5IriWYzBKJyJhdtbZDIbjFIWBTBMy3H0eWZ3Lq43WH+F2jCUj4T+GRTwC3WZ+Xx
+lM/MdnPjDY+sOaRyh1Q9A6xzd38S1Pb/5s35Yq6TET/0jMFg7nuCEiEljBldhEoF
+TcvHa7K33myRFRx0oU6lALHEQ/3Q8fOcvUop14aFQPbSDfi4b2LmprXbDyeT1AaG
+zQl/fsknriQTHhBK6Sthk2nl7EQDu4wnsekGKFIdubNGaMrMvgI1ezqXAgMBAAGj
+XTBbMBwGA1UdEQQVMBOBEWFkbWluQGZyaXBvc3Qub3JnMAwGA1UdEwEB/wQCMAAw
+DgYDVR0PAQH/BAQDAgKkMB0GA1UdDgQWBBS4plbjknpBjMnP8y1rd+6V3Ukr+TAN
+BgkqhkiG9w0BAQ0FAAOCAgEAuNkWmCowz/8+NUL3gDBGIHrRXqlk+5YnD74j/ZrB
+45DBc7vTPj30+C9kBggfmJp9KY/WzpVge4OrvCj7t5HgVCpjA/o63s3zKpQMXqOK
+dSKPEGKqd1pI0rBfTcrdkSd151C3ThCZLfzdq5rQYaNLg4YcAOFjUox97vl5+Odk
+Mgo6VYyF8hKVtIB7IubL2Vcywg3kk3NDS85CCsN5lOWrnAOAvSP/CjIFLqDkuM2A
+L6n+tkcpDl213Xtnf8yzyl3Y0rmc0PtWcBLXOL7+euc5ja3gWVepvNfsnStUt6ik
+0TViwffHOc8N63n7yuADB9tH2+Bx0O32B+fMUzr4j3keOqDkvvxElng9LA2i0pzG
+Luw/jYarnFFwrvhKiwjS0JlmiJnKoclm/OiCl3eCtlQ9hEQfxHzx/n7Kj26W+4Ea
+TPyMbG2YkWuJ+iN+qFse4r6A/vp60BHY+pyyTcZmqiB1xPKqiAEnrYPfxpSnuYzV
+Qi+muD9xyr1IDanlOl4DqHMmhWW4WqUyJhrO9cOtokwvAhZq2r189e/wVlRs+Ysb
+lmpc6sxvx78mJVTJdkaMAac8BBUZ/cWZNIGcmc6XNpRlSIc4Lib9BAC3IVu9FpFA
+GnXpGOAUQ24SUtpt4O45pjbBTHR5ekeOL4sLge6g/lSqXrRBG7mSixGZGw3nbn1O
+gng=
+-----END CERTIFICATE-----
diff --git a/group_vars/all.yml b/group_vars/all.yml
index 25356bf..c7900a6 100644
--- a/group_vars/all.yml
+++ b/group_vars/all.yml
@@ -8,3 +8,18 @@ postfix_instance:
out: { name: out, group: mta, port: 2525 }
MSA: { name: msa }
lists: { name: lists, port: 2527 }
+
+
+# Virtual (non-routable) IPv4 subnet for IPSec. It is always nullrouted
+# on in the absence of xfrm lookup (i.e., when there is no matching
+# IPSec Security Association) to avoid data leaks.
+ipsec_subnet: 172.16.0.0/24
+ipsec:
+ # Virtual (non-routable) addresses for IPSec. They all need to be
+ # distinct and belong to the above subnet 'ipsec_subnet'.
+ antilop: 172.16.0.1
+ benjamin: 172.16.0.2
+ civett: 172.16.0.3
+ elefant: 172.16.0.4
+ giraff: 172.16.0.5
+ mistral: 172.16.0.6
diff --git a/production b/production
index d720ffa..066e469 100644
--- a/production
+++ b/production
@@ -73,3 +73,11 @@ elefant
[backports:children]
webmail
+
+# machines behind NAT
+[NATed:children]
+benjamin
+
+# hostnames resolving to a dynamic IP
+[DynDNS:children]
+benjamin
diff --git a/roles/common/files/etc/logcheck/ignore.d.server/strongswan-local b/roles/common/files/etc/logcheck/ignore.d.server/strongswan-local
new file mode 100644
index 0000000..13218b0
--- /dev/null
+++ b/roles/common/files/etc/logcheck/ignore.d.server/strongswan-local
@@ -0,0 +1,19 @@
+# Ansible Managed
+# Do NOT edit this file directly!
+#
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[JOB\] spawning [[:digit:]]+ worker threads$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[KNL\] creating acquire job for policy [[:xdigit:].:]{3,39}/[[:digit:]]+(\[\w+(/[[:alnum:]-]+)?\])? === [[:xdigit:].:]{3,39}/[[:digit:]]+(\[\w+(/[[:alnum:]-]+)?\])? with reqid \{[[:digit:]]+\}$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[KNL\] creating rekey job for ESP CHILD_SA with SPI [[:xdigit:]]{8} and reqid \{[[:digit:]]+\}$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[KNL\] creating delete job for ESP CHILD_SA with SPI [[:xdigit:]]{8} and reqid \{[[:digit:]]+\}$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[KNL\] querying SAD entry with SPI [[:xdigit:]]{8} failed: No such process \([[:digit:]]+\)$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[IKE\] initiating IKE_SA [[:alnum:]._-]+\[[[:digit:]]+\] to [[:xdigit:].:]{3,39}$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[IKE\] [[:xdigit:].:]{3,39} is initiating an IKE_SA$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[IKE\] establishing CHILD_SA [[:alnum:]._-]+(\{[[:digit:]]+\})?$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[IKE\] IKE_SA [[:alnum:]._-]+\[[[:digit:]]+\] established between [[:xdigit:].:]{3,39}\[[^]\"]+\]\.\.\.[[:xdigit:].:]{3,39}\[[^]]+\]$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[IKE\] CHILD_SA [[:alnum:]._-]+\{[[:digit:]]+\} established with SPIs [[:xdigit:]]{8}_i [[:xdigit:]]{8}_o and TS [[:xdigit:].:]{3,39}/[[:digit:]]+ === [[:xdigit:].:]{3,39}/[[:digit:]]+$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[IKE\] closing CHILD_SA [[:alnum:]._-]+\{[[:digit:]]+\} with SPIs [[:xdigit:]]{8}_i \([[:digit:]]+ bytes\) [[:xdigit:]]{8}_o \([[:digit:]]+ bytes\) and TS [[:xdigit:].:]{3,39}/[[:digit:]]+ === [[:xdigit:].:]{3,39}/[[:digit:]]+$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[IKE\] reauthenticating IKE_SA [[:alnum:]._-]+\[[[:digit:]]+\]$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[JOB\] deleting IKE_SA after [[:digit:]]+ seconds of CHILD_SA inactivity$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[IKE\] deleting IKE_SA [[:alnum:]._-]+\[[[:digit:]]+\] between [[:xdigit:].:]{3,39}\[[^]\"]+\]\.\.\.[[:xdigit:].:]{3,39}\[[^]]+\]$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ (charon|ipsec\[[[:digit:]]+\]): [[:digit:]]+\[IKE\] IKE_SA deleted$
+^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ vpn: [+-] .* [[:xdigit:].:]{3,39}/[[:digit:]]+ == [[:xdigit:].:]{3,39} -- [[:xdigit:].:]{3,39} == [[:xdigit:].:]{3,39}/[[:digit:]]+$
diff --git a/roles/common/files/etc/strongswan.d/charon.conf b/roles/common/files/etc/strongswan.d/charon.conf
new file mode 100644
index 0000000..17e917a
--- /dev/null
+++ b/roles/common/files/etc/strongswan.d/charon.conf
@@ -0,0 +1,303 @@
+# Options for the charon IKE daemon.
+charon {
+
+ # Accept unencrypted ID and HASH payloads in IKEv1 Main Mode.
+ # accept_unencrypted_mainmode_messages = no
+
+ # Maximum number of half-open IKE_SAs for a single peer IP.
+ # block_threshold = 5
+
+ # Whether relations in validated certificate chains should be cached in
+ # memory.
+ # cert_cache = yes
+
+ # Send Cisco Unity vendor ID payload (IKEv1 only).
+ # cisco_unity = no
+
+ # Close the IKE_SA if setup of the CHILD_SA along with IKE_AUTH failed.
+ # close_ike_on_child_failure = no
+
+ # Number of half-open IKE_SAs that activate the cookie mechanism.
+ # cookie_threshold = 10
+
+ # Use ANSI X9.42 DH exponent size or optimum size matched to cryptographic
+ # strength.
+ # dh_exponent_ansi_x9_42 = yes
+
+ # DNS server assigned to peer via configuration payload (CP).
+ # dns1 =
+
+ # DNS server assigned to peer via configuration payload (CP).
+ # dns2 =
+
+ # Enable Denial of Service protection using cookies and aggressiveness
+ # checks.
+ # dos_protection = yes
+
+ # Compliance with the errata for RFC 4753.
+ # ecp_x_coordinate_only = yes
+
+ # Free objects during authentication (might conflict with plugins).
+ # flush_auth_cfg = no
+
+ # Maximum size (complete IP datagram size in bytes) of a sent IKE fragment
+ # when using proprietary IKEv1 or standardized IKEv2 fragmentation (0 for
+ # address family specific default values). If specified this limit is
+ # used for both IPv4 and IPv6.
+ # fragment_size = 0
+
+ # Name of the group the daemon changes to after startup.
+ # group =
+
+ # Timeout in seconds for connecting IKE_SAs (also see IKE_SA_INIT DROPPING).
+ # half_open_timeout = 30
+
+ # Enable hash and URL support.
+ # hash_and_url = no
+
+ # Allow IKEv1 Aggressive Mode with pre-shared keys as responder.
+ # i_dont_care_about_security_and_use_aggressive_mode_psk = no
+
+ # A space-separated list of routing tables to be excluded from route
+ # lookups.
+ # ignore_routing_tables =
+
+ # Maximum number of IKE_SAs that can be established at the same time before
+ # new connection attempts are blocked.
+ # ikesa_limit = 0
+
+ # Number of exclusively locked segments in the hash table.
+ # ikesa_table_segments = 1
+
+ # Size of the IKE_SA hash table.
+ # ikesa_table_size = 1
+
+ # Whether to close IKE_SA if the only CHILD_SA closed due to inactivity.
+ inactivity_close_ike = yes
+
+ # Limit new connections based on the current number of half open IKE_SAs,
+ # see IKE_SA_INIT DROPPING in strongswan.conf(5).
+ # init_limit_half_open = 0
+
+ # Limit new connections based on the number of queued jobs.
+ # init_limit_job_load = 0
+
+ # Causes charon daemon to ignore IKE initiation requests.
+ # initiator_only = no
+
+ # Install routes into a separate routing table for established IPsec
+ # tunnels.
+ install_routes = no
+
+ # Install virtual IP addresses.
+ install_virtual_ip = no
+
+ # The name of the interface on which virtual IP addresses should be
+ # installed.
+ # install_virtual_ip_on =
+
+ # Check daemon, libstrongswan and plugin integrity at startup.
+ # integrity_test = no
+
+ # A comma-separated list of network interfaces that should be ignored, if
+ # interfaces_use is specified this option has no effect.
+ # interfaces_ignore =
+
+ # A comma-separated list of network interfaces that should be used by
+ # charon. All other interfaces are ignored.
+ # interfaces_use =
+
+ # NAT keep alive interval.
+ # keep_alive = 20s
+
+ # Plugins to load in the IKE daemon charon.
+ # load =
+
+ # Determine plugins to load via each plugin's load option.
+ # load_modular = no
+
+ # Maximum packet size accepted by charon.
+ # max_packet = 10000
+
+ # Enable multiple authentication exchanges (RFC 4739).
+ # multiple_authentication = yes
+
+ # WINS servers assigned to peer via configuration payload (CP).
+ # nbns1 =
+
+ # WINS servers assigned to peer via configuration payload (CP).
+ # nbns2 =
+
+ # UDP port used locally. If set to 0 a random port will be allocated.
+ # port = 500
+
+ # UDP port used locally in case of NAT-T. If set to 0 a random port will be
+ # allocated. Has to be different from charon.port, otherwise a random port
+ # will be allocated.
+ # port_nat_t = 4500
+
+ # By default public IPv6 addresses are preferred over temporary ones (RFC
+ # 4941), to make connections more stable. Enable this option to reverse
+ # this.
+ # prefer_temporary_addrs = no
+
+ # Process RTM_NEWROUTE and RTM_DELROUTE events.
+ # process_route = yes
+
+ # Delay in ms for receiving packets, to simulate larger RTT.
+ # receive_delay = 0
+
+ # Delay request messages.
+ # receive_delay_request = yes
+
+ # Delay response messages.
+ # receive_delay_response = yes
+
+ # Specific IKEv2 message type to delay, 0 for any.
+ # receive_delay_type = 0
+
+ # Size of the AH/ESP replay window, in packets.
+ # replay_window = 32
+
+ # Base to use for calculating exponential back off, see IKEv2 RETRANSMISSION
+ # in strongswan.conf(5).
+ # retransmit_base = 1.8
+
+ # Timeout in seconds before sending first retransmit.
+ # retransmit_timeout = 4.0
+
+ # Number of times to retransmit a packet before giving up.
+ # retransmit_tries = 5
+
+ # Interval to use when retrying to initiate an IKE_SA (e.g. if DNS
+ # resolution failed), 0 to disable retries.
+ # retry_initiate_interval = 0
+
+ # Initiate CHILD_SA within existing IKE_SAs.
+ # reuse_ikesa = yes
+
+ # Numerical routing table to install routes to.
+ # routing_table =
+
+ # Priority of the routing table.
+ # routing_table_prio =
+
+ # Delay in ms for sending packets, to simulate larger RTT.
+ # send_delay = 0
+
+ # Delay request messages.
+ # send_delay_request = yes
+
+ # Delay response messages.
+ # send_delay_response = yes
+
+ # Specific IKEv2 message type to delay, 0 for any.
+ # send_delay_type = 0
+
+ # Send strongSwan vendor ID payload
+ # send_vendor_id = no
+
+ # Number of worker threads in charon.
+ # threads = 16
+
+ # Name of the user the daemon changes to after startup.
+ # user =
+
+ crypto_test {
+
+ # Benchmark crypto algorithms and order them by efficiency.
+ # bench = no
+
+ # Buffer size used for crypto benchmark.
+ # bench_size = 1024
+
+ # Number of iterations to test each algorithm.
+ # bench_time = 50
+
+ # Test crypto algorithms during registration (requires test vectors
+ # provided by the test-vectors plugin).
+ # on_add = no
+
+ # Test crypto algorithms on each crypto primitive instantiation.
+ # on_create = no
+
+ # Strictly require at least one test vector to enable an algorithm.
+ # required = no
+
+ # Whether to test RNG with TRUE quality; requires a lot of entropy.
+ # rng_true = no
+
+ }
+
+ host_resolver {
+
+ # Maximum number of concurrent resolver threads (they are terminated if
+ # unused).
+ # max_threads = 3
+
+ # Minimum number of resolver threads to keep around.
+ # min_threads = 0
+
+ }
+
+ leak_detective {
+
+ # Includes source file names and line numbers in leak detective output.
+ # detailed = yes
+
+ # Threshold in bytes for leaks to be reported (0 to report all).
+ # usage_threshold = 10240
+
+ # Threshold in number of allocations for leaks to be reported (0 to
+ # report all).
+ # usage_threshold_count = 0
+
+ }
+
+ processor {
+
+ # Section to configure the number of reserved threads per priority class
+ # see JOB PRIORITY MANAGEMENT in strongswan.conf(5).
+ priority_threads {
+
+ }
+
+ }
+
+ # Section containing a list of scripts (name = path) that are executed when
+ # the daemon is started.
+ start-scripts {
+
+ }
+
+ # Section containing a list of scripts (name = path) that are executed when
+ # the daemon is terminated.
+ stop-scripts {
+
+ }
+
+ tls {
+
+ # List of TLS encryption ciphers.
+ # cipher =
+
+ # List of TLS key exchange methods.
+ # key_exchange =
+
+ # List of TLS MAC algorithms.
+ # mac =
+
+ # List of TLS cipher suites.
+ # suites =
+
+ }
+
+ x509 {
+
+ # Discard certificates with unsupported or unknown critical extensions.
+ # enforce_critical = yes
+
+ }
+
+}
+
diff --git a/roles/common/files/etc/strongswan.d/charon/socket-default.conf b/roles/common/files/etc/strongswan.d/charon/socket-default.conf
new file mode 100644
index 0000000..1bc20f1
--- /dev/null
+++ b/roles/common/files/etc/strongswan.d/charon/socket-default.conf
@@ -0,0 +1,20 @@
+socket-default {
+
+ # Firewall mark to set on outbound packets.
+ # fwmark =
+
+ # Whether to load the plugin. Can also be an integer to increase the
+ # priority of this plugin.
+ load = yes
+
+ # Set source address on outbound packets, if possible.
+ # set_source = yes
+
+ # Listen on IPv4, if possible.
+ # use_ipv4 = yes
+
+ # Listen on IPv6, if possible.
+ use_ipv6 = no
+
+}
+
diff --git a/roles/common/files/usr/local/sbin/update-firewall.sh b/roles/common/files/usr/local/sbin/update-firewall.sh
index f25f507..065bae2 100755
--- a/roles/common/files/usr/local/sbin/update-firewall.sh
+++ b/roles/common/files/usr/local/sbin/update-firewall.sh
@@ -40,8 +40,12 @@ check=0
verbose=0
addrfam=
-secmark=0xA99 # must match that in /etc/network/if-up.d/ipsec
-secproto=esp # must match /etc/ipsec.conf; ESP is the default (vs AH/IPComp)
+secproto=esp # must match /etc/ipsec.conf; ESP is the default (vs AH/IPComp)
+if [ -x /usr/sbin/ipsec ] && /usr/sbin/ipsec status >/dev/null; then
+ ipsec=y
+else
+ ipsec=n
+fi
fail2ban_re='^(\[[0-9]+:[0-9]+\]\s+)?-A fail2ban-\S'
IPSec_re=" -m policy --dir (in|out) --pol ipsec --reqid [0-9]+ --proto $secproto -j ACCEPT$"
@@ -152,21 +156,9 @@ run() {
tables[$f]=filter
# The default interface associated with this address.
- local if=$( /bin/ip -$f route show to default scope global \
+ local if=$( /bin/ip -$f -o route show to default scope global \
| sed -nr '/^default via \S+ dev (\S+).*/ {s//\1/p;q}' )
- # The virtual interface reserved for IPSec.
- local ifsec=$( /bin/ip -o -$f link show \
- | sed -nr "/^[0-9]+:\s+(sec[0-9]+)@$if:\s.*/ {s//\1/p;q}" )
-
- # The (host-scoped) IP reserved for IPSec.
- local ipsec=
- if [ "$ifsec" -a $f = 4 ]; then
- tables[$f]='mangle nat filter'
- ipsec=$( /bin/ip -$f address show dev "$ifsec" scope host \
- | sed -nr '/^\s+inet\s(\S+).*/ {s//\1/p;q}' )
- fi
-
# Store the old (current) ruleset
local old=$(mktemp --tmpdir current-rules.v$f.XXXXXX) \
new=$(mktemp --tmpdir new-rules.v$f.XXXXXX)
@@ -203,8 +195,9 @@ run() {
grep -E -- "$fail2ban_re" "$old" || true
fi >> "$new"
- if [ "$ipsec" ]; then
- # (Host-to-host) IPSec tunnels come first. TODO: test IPSec with IPv6.
+ if [ "$f" = 4 -a "$ipsec" = y ]; then
+ # Our IPSec tunnels are IPv4 only.
+ # (Host-to-host) IPSec tunnels come first.
grep -E -- "$IPSec_re" "$old" >> "$new" || true
# Allow any IPsec $secproto protocol packets to be sent and received.
@@ -219,15 +212,24 @@ run() {
# http://baldric.net/loose-iptables-firewall-for-servers/
local ip
- if [ "$f" = 4 ]; then
+ if [ "$f" = 4 -a "$ipsec" = y ]; then
# Private-use networks (RFC 1918) and link local (RFC 3927)
- local MyNetwork=$( /bin/ip -4 address show dev $if scope global \
- | sed -nr 's/^\s+inet\s(\S+).*/\1/p')
+ local MyIPSec="$( /bin/ip -4 -o route show table 220 dev $if | sed 's/\s.*//' )"
+ local MyNetwork="$( /bin/ip -4 -o address show dev $if scope global \
+ | sed -nr "s/^[0-9]+:\s+$if\s+inet\s(\S+).*/\1/p" \
+ | while read ip; do
+ for ips in $MyIPSec; do
+ [ "$ips" = "$(/usr/bin/netmask -nc "$ip" "$ips" | sed 's/^ *//')" ] || echo "$ip"
+ done
+ done
+ )"
[ "$MyNetwork" ] && \
for ip in 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 169.254.0.0/16; do
# Don't lock us out if we are behind a NAT ;-)
- [ "$ip" = "$(/usr/bin/netmask -nc $ip $MyNetwork | sed 's/ //g')" ] \
- || iptables -A INPUT -i $if -s "$ip" -j DROP
+ for myip in $MyNetwork; do
+ [ "$ip" = "$(/usr/bin/netmask -nc "$ip" "$myip" | sed 's/^ *//')" ] \
+ || iptables -A INPUT -i $if -s "$ip" -j DROP
+ done
done
# Other martian packets: "This" network, multicast, broadcast (RFCs
@@ -259,14 +261,14 @@ run() {
local localhost=$(inet46 $f '127.0.0.1/8' '::1/128')
iptables -A INPUT -i lo -s "$localhost" -d "$localhost" -j ACCEPT
iptables -A OUTPUT -o lo -s "$localhost" -d "$localhost" -j ACCEPT
-
- if [ "$ipsec" ]; then
- # ACCEPT any, *IPSec* traffic destinating to the non-routable
- # $ipsec. Also ACCEPT all traffic originating from $ipsec, as
- # it is MASQUERADE'd.
- iptables -A INPUT -d "$ipsec" -i $if -m policy --dir in \
- --pol ipsec --proto $secproto -j ACCEPT
- iptables -A OUTPUT -m mark --mark "$secmark" -o $if -j ACCEPT
+ if [ "$f" = 4 -a "$ipsec" = y ]; then
+ # Allow local access to our virtual IP
+ /bin/ip -4 -o route show table 220 dev $if \
+ | sed -nr 's/.*\ssrc\s+([[:digit:].]{7,15})(\s.*)?/\1/p' \
+ | while read ipsec; do
+ iptables -A INPUT -i lo -s "$ipsec" -d "$ipsec" -j ACCEPT
+ iptables -A OUTPUT -o lo -s "$ipsec" -d "$ipsec" -j ACCEPT
+ done
fi
# Prepare fail2ban. We make fail2ban insert its rules in a
@@ -330,46 +332,6 @@ run() {
########################################################################
commit
- if [ "$ipsec" ]; then
- # DNAT the IPSec paquets to $ipsec after decapsulation, and SNAT
- # them before encapsulation. We need to do the NAT'ing before
- # packets enter the IPSec stack because they are signed
- # afterwards, and NAT'ing would mess up the signature.
- ipt-chains mangle PREROUTING:ACCEPT INPUT:ACCEPT \
- FORWARD:DROP \
- OUTPUT:ACCEPT POSTROUTING:ACCEPT
-
- # Packets which destination is $ipsec *must* be associated with
- # an IPSec policy.
- iptables -A INPUT -d "$ipsec" -i $if -m policy --dir in \
- --pol ipsec --proto $secproto -j ACCEPT
- iptables -A INPUT -d "$ipsec" -i $if -j DROP
-
- # Packets originating from our (non-routable) $ipsec are marked;
- # if there is no xfrm lookup (i.e., no matching IPSec
- # association), the packet will retain its mark and be null
- # routed later on. Otherwise, the packet is re-queued unmarked.
- iptables -A OUTPUT -o $if -j MARK --set-mark 0x0
- iptables -A OUTPUT -s "$ipsec" -o $if -m policy --dir out \
- --pol none -j MARK --set-mark $secmark
- commit
-
- ipt-chains nat PREROUTING:ACCEPT INPUT:ACCEPT \
- OUTPUT:ACCEPT POSTROUTING:ACCEPT
-
- # DNAT all marked packets after decapsulation.
- iptables -A PREROUTING \! -d "$ipsec" -i $if -m policy --dir in \
- --pol ipsec --proto $secproto -j DNAT --to "${ipsec%/*}"
-
- # Packets originating from our IPSec are SNAT'ed (MASQUERADE).
- # (And null-routed later on unless there is an xfrm
- # association.)
- iptables -A POSTROUTING -m mark --mark $secmark -o $if -j MASQUERADE
- commit
- fi
-
- ########################################################################
-
local rv1=0 rv2=0 persistent=/etc/iptables/rules.v$f
local oldz=$(mktemp --tmpdir current-rules.v$f.XXXXXX)
diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml
index ebb40a0..6ca53be 100644
--- a/roles/common/handlers/main.yml
+++ b/roles/common/handlers/main.yml
@@ -17,9 +17,15 @@
- name: Update rkhunter's data file
command: /usr/bin/rkhunter --propupd
+- name: Update firewall
+ command: /usr/local/sbin/update-firewall.sh -c
+
- name: Restart fail2ban
service: name=fail2ban state=restarted
+- name: Restart IPSec
+ service: name=ipsec state=restarted
+
- name: Reload networking
# /etc/init.d/networking doesn't answer the status command; but since
# it should be "up" whenever ansible has access to the machine, we use
diff --git a/roles/common/tasks/ipsec.yml b/roles/common/tasks/ipsec.yml
new file mode 100644
index 0000000..b82c281
--- /dev/null
+++ b/roles/common/tasks/ipsec.yml
@@ -0,0 +1,96 @@
+- name: Install strongSwan
+ apt: pkg={{ item }}
+ with_items:
+ - strongswan-charon
+ # for the GCM and openssl plugins
+ - libstrongswan-standard-plugins
+ notify:
+ - Update firewall
+ - Restart IPSec
+
+- name: Auto-create a dedicated virtual subnet for IPSec
+ template: src=etc/network/if-up.d/ipsec.j2
+ dest=/etc/network/if-up.d/ipsec
+ owner=root group=root
+ mode=0755
+ notify:
+ - Reload networking
+
+- name: Auto-deactivate the dedicated virtual subnet for IPSec
+ file: src=../if-up.d/ipsec
+ dest=/etc/network/if-down.d/ipsec
+ owner=root group=root state=link force=yes
+
+- meta: flush_handlers
+
+
+- name: Configure IPSec
+ template: src=etc/ipsec.conf.j2
+ dest=/etc/ipsec.conf
+ owner=root group=root
+ mode=0644
+ register: r1
+ notify:
+ - Restart IPSec
+
+- name: Configure IPSec's secrets
+ template: src=etc/ipsec.secrets.j2
+ dest=/etc/ipsec.secrets
+ owner=root group=root
+ mode=0600
+ register: r2
+ notify:
+ - Restart IPSec
+
+- name: Configure Charon
+ copy: src=etc/strongswan.d/{{ item }}
+ dest=/etc/strongswan.d/{{ item }}
+ owner=root group=root
+ mode=0644
+ with_items:
+ - charon.conf
+ - charon/socket-default.conf
+ register: r3
+ notify:
+ - Restart IPSec
+
+- name: Generate a private key and a X.509 certificate for IPSec
+ command: genkeypair.sh x509
+ --pubkey=/etc/ipsec.d/certs/{{ inventory_hostname_short }}.pem
+ --privkey=/etc/ipsec.d/private/{{ inventory_hostname_short }}.key
+ --ou=IPSec --cn={{ inventory_hostname_short }}
+ -t rsa -b 4096 -h sha512
+ register: r4
+ changed_when: r4.rc == 0
+ failed_when: r4.rc > 1
+ notify:
+ - Restart IPSec
+ tags:
+ - genkey
+
+- name: Fetch IPSec X.509 certificate
+ # Ensure we don't fetch private data
+ become: False
+ fetch_cmd: cmd="openssl x509"
+ stdin=/etc/ipsec.d/certs/{{ inventory_hostname_short }}.pem
+ dest=certs/ipsec/{{ inventory_hostname_short }}.pem
+ tags:
+ - genkey
+
+# Don't copy our pubkey due to a possible race condition. Only the
+# remote machine has authority regarding its key.
+- name: Copy IPSec X.509 certificates (except ours)
+ copy: src=certs/ipsec/{{ hostvars[item].inventory_hostname_short }}.pem
+ dest=/etc/ipsec.d/certs/{{ hostvars[item].inventory_hostname_short }}.pem
+ owner=root group=root
+ mode=0644
+ with_items: "{{ groups.all | difference([inventory_hostname]) }}"
+ register: r5
+ tags:
+ - genkey
+ notify:
+ - Restart IPSec
+
+- name: Start IPSec
+ service: name=ipsec state=started
+ when: not (r1.changed or r2.changed or r3.changed or r4.changed or r5.changed)
diff --git a/roles/common/tasks/logging.yml b/roles/common/tasks/logging.yml
index 3b86294..b27fc41 100644
--- a/roles/common/tasks/logging.yml
+++ b/roles/common/tasks/logging.yml
@@ -47,6 +47,7 @@
- ignore.d.server/common-local
- ignore.d.server/dovecot-local
- ignore.d.server/postfix-local
+ - ignore.d.server/strongswan-local
# logcheck-sudo already exists, but changing the filename for our
# local modifications would defeat the ruleset
- violations.ignore.d/logcheck-sudo
diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml
index 1226d37..88d44f3 100644
--- a/roles/common/tasks/main.yml
+++ b/roles/common/tasks/main.yml
@@ -47,6 +47,11 @@
command: gendhparam.sh /etc/ssl/dhparams.pem 2048
creates=/etc/ssl/dhparams.pem
tags: genkey
+- include: ipsec.yml
+ tags:
+ - strongswan
+ - ipsec
+ when: "groups.all | length > 1"
- include: logging.yml
tags: logging
- include: ntp.yml
diff --git a/roles/common/templates/etc/fail2ban/jail.local.j2 b/roles/common/templates/etc/fail2ban/jail.local.j2
index f1c9833..eb6a7fb 100644
--- a/roles/common/templates/etc/fail2ban/jail.local.j2
+++ b/roles/common/templates/etc/fail2ban/jail.local.j2
@@ -14,7 +14,7 @@ chain = fail2ban
action = %(action_)s
# Don't ban ourselves.
-ignoreip = 127.0.0.0/8 {{ groups.all | sort | join(' ') }}
+ignoreip = 127.0.0.0/8 {{ ipsec_subnet }}
#
# JAILS
diff --git a/roles/common/templates/etc/ipsec.conf.j2 b/roles/common/templates/etc/ipsec.conf.j2
new file mode 100644
index 0000000..4d6aa68
--- /dev/null
+++ b/roles/common/templates/etc/ipsec.conf.j2
@@ -0,0 +1,43 @@
+# {{ ansible_managed }}
+# Do NOT edit this file directly!
+
+config setup
+ charondebug = "dmn 0, lib 0, cfg 0, ike 0, enc 0, net 0"
+
+conn %default
+ keyexchange = ikev2
+ keyingtries = %forever
+ ike = aes128gcm16-prfsha256-ecp256,aes256gcm16-prfsha384-ecp384!
+ esp = aes128gcm16-ecp256,aes256gcm16-ecp384!
+{% if 'NATed' not in group_names %}
+ mobike = no
+{% endif %}
+{% if 'DynDNS' in group_names %}
+ leftallowany = yes
+{% endif %}
+ leftauth = pubkey
+ left = %defaultroute
+ leftsubnet = {{ ipsec[inventory_hostname_short] | ipv4 }}/32
+ leftcert = {{ inventory_hostname_short }}.pem
+ leftfirewall = yes
+ lefthostaccess = yes
+ rightauth = pubkey
+ auto = route
+ dpdaction = hold
+ inactivity = 30m
+ modeconfig = push
+
+{% for host in groups.all | difference([inventory_hostname]) | sort %}
+
+conn {{ hostvars[host].inventory_hostname_short }}
+ right = {{ hostvars[host].inventory_hostname }}
+{% if 'DynDNS' in hostvars[host].group_names %}
+ rightallowany = yes
+{% endif %}
+ rightcert = {{ hostvars[host].inventory_hostname_short }}.pem
+ rightsubnet = {{ ipsec[ hostvars[host].inventory_hostname_short ] | ipv4 }}/32
+{% if 'NATed' not in group_names and 'NATed' in hostvars[host].group_names %}
+ mobike = yes
+{% endif %}
+
+{%- endfor %}
diff --git a/roles/common/templates/etc/ipsec.secrets.j2 b/roles/common/templates/etc/ipsec.secrets.j2
new file mode 100644
index 0000000..6ed670d
--- /dev/null
+++ b/roles/common/templates/etc/ipsec.secrets.j2
@@ -0,0 +1,5 @@
+# {{ ansible_managed }}
+# Do NOT edit this file directly!
+
+# Our VPN uses RSA only.
+: RSA {{ inventory_hostname_short }}.key
diff --git a/roles/common/templates/etc/iptables/services.j2 b/roles/common/templates/etc/iptables/services.j2
index 303fa06..6bd2533 100644
--- a/roles/common/templates/etc/iptables/services.j2
+++ b/roles/common/templates/etc/iptables/services.j2
@@ -4,6 +4,13 @@
# direction protocol destination port source port
# (in|out|inout)[46]? (tcp|udp|..) (port|port:port|port,port) (port|port:port|port,port)
+{% if groups.all | length > 1 %}
+inout4 udp 500 500 # ISAKMP
+{% if groups.NATed | length > 0 %}
+inout4 udp 4500 4500 # IPSec NAT Traversal
+{% endif %}
+{% endif %}
+
out tcp 80,443 # HTTP/HTTPS
out tcp 9418 # GIT
out udp 53 # DNS
diff --git a/roles/common/templates/etc/network/if-up.d/ipsec.j2 b/roles/common/templates/etc/network/if-up.d/ipsec.j2
new file mode 100755
index 0000000..7dd41d4
--- /dev/null
+++ b/roles/common/templates/etc/network/if-up.d/ipsec.j2
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# A post-up/down hook to automatically create/delete a virtual subnet
+# for IPSec (inet4 only).
+# Copyright © 2016 Guilhem Moulin <guilhem@fripost.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+set -ue
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+# Ignore the loopback interface and non inet4 families.
+[ "$IFACE" != lo -a "$ADDRFAM" = inet ] || exit 0
+
+# Only the device with the default, globally-scoped route, is of
+# interest here.
+ip="$( ip -4 -o route show to default scope global \
+ | sed -nr '/^default via (\S+) dev (\S+).*/ {s//\2 \1/p;q}' )"
+[ "${ip% *}" = "$IFACE" ] || exit 0
+ip="${ip##* }"
+
+vip="{{ ipsec[inventory_hostname_short] }}"
+vsubnet="{{ ipsec_subnet }}"
+
+case "$MODE" in
+ start) ip address add "$vip/32" dev "$IFACE" scope global || true
+ # Nullroute the subnet used for IPSec to avoid data leaks
+ # in the absence of xfrm lookup (i.e., when there is no
+ # matching IPSec Security Association).
+ ip route replace prohibit "$vsubnet" proto static || true
+ ip route replace table 220 to "$vsubnet" via "$ip" dev "$IFACE" proto static src "$vip" || true
+ ;;
+ stop) ip route del table 220 to "$vsubnet" via "$ip" dev "$IFACE" proto static src "$vip" || true
+ ip route del prohibit "$vsubnet" proto static || true
+ ip address del "$vip/32" dev "$IFACE" scope global || true
+esac