summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2026-06-25 16:36:22 +0200
committerGitHub <noreply@github.com>2026-06-25 16:36:22 +0200
commitfe78ab4165456fd1d7bcd2ec99d7601dc2e71d2c (patch)
tree474df907283a78040dea704765f10b3b84eb6b0a
parent53cfae0cbd315f5e8e4b8288c1f2382bd6212e87 (diff)
parent11d5ee39fa41f512e343ef6084675a0f372c9e92 (diff)
downloadvyos-1x-fe78ab4165456fd1d7bcd2ec99d7601dc2e71d2c.tar.gz
vyos-1x-fe78ab4165456fd1d7bcd2ec99d7601dc2e71d2c.zip
Merge pull request #5284 from vyos/T8097-strongswan-esn
T8097: strongswan: add CLI for ESN
-rw-r--r--interface-definitions/include/vpn-ipsec-esn.xml.i26
-rw-r--r--interface-definitions/vpn_ipsec.xml.in2
-rwxr-xr-xpython/vyos/template.py11
-rwxr-xr-xsmoketest/scripts/cli/test_vpn_ipsec.py144
4 files changed, 150 insertions, 33 deletions
diff --git a/interface-definitions/include/vpn-ipsec-esn.xml.i b/interface-definitions/include/vpn-ipsec-esn.xml.i
new file mode 100644
index 000000000..b4faa25d5
--- /dev/null
+++ b/interface-definitions/include/vpn-ipsec-esn.xml.i
@@ -0,0 +1,26 @@
+<!-- include start from vpn-ipsec-esn.xml.i -->
+<leafNode name="esn">
+ <properties>
+ <help>Extended Sequence Number (ESN)</help>
+ <completionHelp>
+ <list>optional required disabled</list>
+ </completionHelp>
+ <valueHelp>
+ <format>optional</format>
+ <description>Prefer ESN, but allow 32-bit sequence numbers</description>
+ </valueHelp>
+ <valueHelp>
+ <format>required</format>
+ <description>ESN enabled, accept 64-bit sequence numbers only</description>
+ </valueHelp>
+ <valueHelp>
+ <format>disabled</format>
+ <description>ESN disabled, accept 32-bit sequence numbers only</description>
+ </valueHelp>
+ <constraint>
+ <regex>(optional|required|disabled)</regex>
+ </constraint>
+ </properties>
+ <defaultValue>disabled</defaultValue>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in
index 80490edd6..bda084604 100644
--- a/interface-definitions/vpn_ipsec.xml.in
+++ b/interface-definitions/vpn_ipsec.xml.in
@@ -306,6 +306,7 @@
<children>
#include <include/vpn-ipsec-encryption.xml.i>
#include <include/vpn-ipsec-hash.xml.i>
+ #include <include/vpn-ipsec-esn.xml.i>
</children>
</tagNode>
</children>
@@ -622,6 +623,7 @@
</leafNode>
#include <include/vpn-ipsec-encryption.xml.i>
#include <include/vpn-ipsec-hash.xml.i>
+ #include <include/vpn-ipsec-esn.xml.i>
</children>
</tagNode>
</children>
diff --git a/python/vyos/template.py b/python/vyos/template.py
index 01c60a8b3..c1555aa1c 100755
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -530,6 +530,17 @@ def get_esp_ike_cipher(group_config, ike_group=None):
group = get_first_ike_dh_group(ike_group)
tmp += '-' + pfs_lut[group]
+ # For 'optional' and 'disabled' we need two values as
+ # proposal without '-esn'/'-noesn' is incompatible with
+ # proposals with any of them.
+ if 'esn' in proposal:
+ if proposal['esn'] == 'required':
+ tmp += '-esn'
+ elif proposal['esn'] == 'optional':
+ ciphers.append(tmp + '-esn-noesn')
+ elif proposal['esn'] == 'disabled':
+ ciphers.append(tmp + '-noesn')
+
ciphers.append(tmp)
return ciphers
diff --git a/smoketest/scripts/cli/test_vpn_ipsec.py b/smoketest/scripts/cli/test_vpn_ipsec.py
index 68aef845e..a73cd0b2b 100755
--- a/smoketest/scripts/cli/test_vpn_ipsec.py
+++ b/smoketest/scripts/cli/test_vpn_ipsec.py
@@ -252,8 +252,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'life_bytes = {life_bytes}',
f'life_packets = {life_packets}',
f'rekey_time = 28800s', # default value
- f'proposals = aes128-sha1-modp1024',
- f'esp_proposals = aes128-sha1-modp1024',
+ f'proposals = aes128-sha1-modp1024-noesn,aes128-sha1-modp1024',
+ f'esp_proposals = aes128-sha1-modp1024-noesn,aes128-sha1-modp1024',
f'life_time = 3600s', # default value
f'local_addrs = {local_address} # dhcp:no',
f'remote_addrs = {peer_ip}',
@@ -406,8 +406,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'life_bytes = {life_bytes}',
f'life_packets = {life_packets}',
f'rekey_time = 28800s', # default value
- f'proposals = aes128-sha1-modp1024',
- f'esp_proposals = aes128-sha1-modp1024',
+ f'proposals = aes128-sha1-modp1024-noesn,aes128-sha1-modp1024',
+ f'esp_proposals = aes128-sha1-modp1024-noesn,aes128-sha1-modp1024',
f'life_time = 3600s', # default value
f'local_addrs = {local_address} # dhcp:no',
f'remote_addrs = {peer_ip}',
@@ -482,8 +482,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
swanctl_conf_lines = [
'version = 2',
'auth = psk',
- 'proposals = aes128-sha1-modp1024,aes256-sha1-modp1536',
- 'esp_proposals = aes128-sha1-modp2048,aes256-sha1-modp2048',
+ 'proposals = aes128-sha1-modp1024-noesn,aes128-sha1-modp1024,aes256-sha1-modp1536-noesn,aes256-sha1-modp1536',
+ 'esp_proposals = aes128-sha1-modp2048-noesn,aes128-sha1-modp2048,aes256-sha1-modp2048-noesn,aes256-sha1-modp2048',
'life_time = 3600s',
'mode = transport', # ensure transport mode is used
f'{peer_name}-tunnel-{tunnel_id}',
@@ -549,8 +549,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
swanctl_conf_lines = [
f'version = 2',
f'auth = psk',
- f'proposals = aes128-sha1-modp1024',
- f'esp_proposals = aes128-sha1-modp1024',
+ f'proposals = aes128-sha1-modp1024-noesn,aes128-sha1-modp1024',
+ f'esp_proposals = aes128-sha1-modp1024-noesn,aes128-sha1-modp1024',
f'local_addrs = {local_address} # dhcp:no',
f'mobike = no',
f'remote_addrs = {peer_ip}',
@@ -625,8 +625,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
swanctl_conf_lines = [
f'version = 2',
f'auth = psk',
- f'proposals = aes128-sha1-modp1024',
- f'esp_proposals = aes128-sha1-modp1024',
+ f'proposals = aes128-sha1-modp1024-noesn,aes128-sha1-modp1024',
+ f'esp_proposals = aes128-sha1-modp1024-noesn,aes128-sha1-modp1024',
f'local_addrs = {local_address} # dhcp:no',
f'mobike = no',
f'remote_addrs = {peer_ip}',
@@ -765,8 +765,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'version = 2',
f'auth = psk',
f'rekey_time = 86400s',
- f'proposals = aes256gcm128-sha384-prfsha384-ecp384',
- f'esp_proposals = aes256gcm128-sha384-ecp384',
+ f'proposals = aes256gcm128-sha384-prfsha384-ecp384-noesn,aes256gcm128-sha384-prfsha384-ecp384',
+ f'esp_proposals = aes256gcm128-sha384-ecp384-noesn,aes256gcm128-sha384-ecp384',
f'life_time = 28800s', # default value
f'local_addrs = {local_address} # dhcp:no',
f'remote_addrs = {peer_ip}',
@@ -869,22 +869,24 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
swanctl_conf = read_file(swanctl_file)
swanctl_lines = [
- f'proposals = aes256-sha1-prfsha1-modp1024',
+ f'proposals = aes256-sha1-prfsha1-modp1024-noesn,aes256-sha1-prfsha1-modp1024',
f'version = 1',
f'rekey_time = {ike_lifetime}s',
f'rekey_time = {esp_lifetime}s',
- f'esp_proposals = aes256-sha1-modp1024,3des-md5-modp1024',
+ f'esp_proposals = aes256-sha1-modp1024-noesn,aes256-sha1-modp1024,3des-md5-modp1024-noesn,3des-md5-modp1024',
f'local_ts = dynamic[gre]',
f'remote_ts = dynamic[gre]',
f'mode = transport',
f'secret = {nhrp_secret}',
'unique = never',
]
- for line in swanctl_lines:
- self.assertIn(line, swanctl_conf)
-
- # There is only one NHRP test so no need to delete this globally in tearDown()
- self.cli_delete(nhrp_path)
+ try:
+ for line in swanctl_lines:
+ self.assertIn(line, swanctl_conf)
+ finally:
+ # There is only one NHRP test so no need to delete this globally in tearDown()
+ # try/finally so that it is deleted even if test fails, otherwise we get errors
+ self.cli_delete(nhrp_path)
def test_site_to_site_x509(self):
# Enable PKI
@@ -930,8 +932,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'id = "{peer_name}"',
f'auth = pubkey',
f'certs = {peer_name}.pem',
- f'proposals = aes128-sha1-modp1024',
- f'esp_proposals = aes128-sha1-modp1024',
+ f'proposals = aes128-sha1-modp1024-noesn,aes128-sha1-modp1024',
+ f'esp_proposals = aes128-sha1-modp1024-noesn,aes128-sha1-modp1024',
f'local_addrs = {local_address} # dhcp:no',
f'remote_addrs = {peer_ip}',
f'local_ts = 0.0.0.0/0,::/0',
@@ -1186,7 +1188,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'{conn_name}',
f'remote_addrs = %any',
f'local_addrs = {local_address}',
- f'proposals = aes256-sha512-modp2048,aes256-sha256-modp2048,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048',
+ f'proposals = aes256-sha512-modp2048-noesn,aes256-sha512-modp2048,aes256-sha256-modp2048-noesn,aes256-sha256-modp2048,aes256-sha256-modp1024-noesn,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048-noesn,aes128gcm128-sha256-modp2048',
f'version = 2',
f'send_certreq = no',
f'rekey_time = {ike_lifetime}s',
@@ -1197,7 +1199,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'certs = peer1.pem',
f'auth = eap-mschapv2',
f'eap_id = %any',
- f'esp_proposals = aes256-sha512,aes256-sha384,aes256-sha256,aes256-sha1,aes128gcm128-sha256',
+ f'esp_proposals = aes256-sha512-noesn,aes256-sha512,aes256-sha384-noesn,aes256-sha384,aes256-sha256-noesn,aes256-sha256,aes256-sha1-noesn,aes256-sha1,aes128gcm128-sha256-noesn,aes128gcm128-sha256',
f'life_time = {eap_lifetime}s',
f'dpd_action = clear',
f'replay_window = 32',
@@ -1306,7 +1308,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'{conn_name}',
f'remote_addrs = %any',
f'local_addrs = {local_address}',
- f'proposals = aes256-sha512-modp2048,aes256-sha256-modp2048,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048',
+ f'proposals = aes256-sha512-modp2048-noesn,aes256-sha512-modp2048,aes256-sha256-modp2048-noesn,aes256-sha256-modp2048,aes256-sha256-modp1024-noesn,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048-noesn,aes128gcm128-sha256-modp2048',
f'version = 2',
f'send_certreq = no',
f'rekey_time = {ike_lifetime}s',
@@ -1318,7 +1320,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'cacerts = MyVyOS-CA.pem',
f'auth = eap-tls',
f'eap_id = %any',
- f'esp_proposals = aes256-sha512,aes256-sha384,aes256-sha256,aes256-sha1,aes128gcm128-sha256',
+ f'esp_proposals = aes256-sha512-noesn,aes256-sha512,aes256-sha384-noesn,aes256-sha384,aes256-sha256-noesn,aes256-sha256,aes256-sha1-noesn,aes256-sha1,aes128gcm128-sha256-noesn,aes128gcm128-sha256',
f'life_time = {eap_lifetime}s',
f'dpd_action = clear',
f'inactivity = 28800',
@@ -1422,7 +1424,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'{conn_name}',
f'remote_addrs = %any',
f'local_addrs = {local_address}',
- f'proposals = aes256-sha512-modp2048,aes256-sha256-modp2048,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048',
+ f'proposals = aes256-sha512-modp2048-noesn,aes256-sha512-modp2048,aes256-sha256-modp2048-noesn,aes256-sha256-modp2048,aes256-sha256-modp1024-noesn,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048-noesn,aes128gcm128-sha256-modp2048',
f'version = 2',
f'send_certreq = no',
f'rekey_time = {ike_lifetime}s',
@@ -1432,7 +1434,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'auth = pubkey',
f'certs = peer1.pem',
f'cacerts = MyVyOS-CA.pem,MyVyOS-IntCA.pem',
- f'esp_proposals = aes256-sha512,aes256-sha384,aes256-sha256,aes256-sha1,aes128gcm128-sha256',
+ f'esp_proposals = aes256-sha512-noesn,aes256-sha512,aes256-sha384-noesn,aes256-sha384,aes256-sha256-noesn,aes256-sha256,aes256-sha1-noesn,aes256-sha1,aes128gcm128-sha256-noesn,aes128gcm128-sha256',
f'life_time = {eap_lifetime}s',
f'dpd_action = clear',
f'inactivity = 28800',
@@ -1620,7 +1622,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'{conn_name}',
f'remote_addrs = %any',
f'local_addrs = {local_address}',
- f'proposals = aes256-sha512-modp2048,aes256-sha256-modp2048,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048',
+ f'proposals = aes256-sha512-modp2048-noesn,aes256-sha512-modp2048,aes256-sha256-modp2048-noesn,aes256-sha256-modp2048,aes256-sha256-modp1024-noesn,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048-noesn,aes128gcm128-sha256-modp2048',
f'version = 2',
f'send_certreq = no',
f'rekey_time = 0s',
@@ -1630,7 +1632,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'auth = pubkey',
f'certs = peer1.pem',
f'cacerts = MyVyOS-CA.pem,MyVyOS-IntCA.pem',
- f'esp_proposals = aes256-sha512,aes256-sha384,aes256-sha256,aes256-sha1,aes128gcm128-sha256',
+ f'esp_proposals = aes256-sha512-noesn,aes256-sha512,aes256-sha384-noesn,aes256-sha384,aes256-sha256-noesn,aes256-sha256,aes256-sha1-noesn,aes256-sha1,aes128gcm128-sha256-noesn,aes128gcm128-sha256',
f'life_time = {eap_lifetime}s',
f'rekey_time = 0s',
f'dpd_action = clear',
@@ -1733,7 +1735,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'{conn_name}',
f'remote_addrs = %any',
f'local_addrs = {local_address}',
- f'proposals = aes256-sha512-modp2048,aes256-sha256-modp2048,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048',
+ f'proposals = aes256-sha512-modp2048-noesn,aes256-sha512-modp2048,aes256-sha256-modp2048-noesn,aes256-sha256-modp2048,aes256-sha256-modp1024-noesn,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048-noesn,aes128gcm128-sha256-modp2048',
f'version = 2',
f'send_certreq = no',
f'rekey_time = {ike_lifetime}s',
@@ -1744,7 +1746,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'certs = peer1.pem',
f'auth = eap-mschapv2',
f'eap_id = %any',
- f'esp_proposals = aes256-sha512,aes256-sha384,aes256-sha256,aes256-sha1,aes128gcm128-sha256',
+ f'esp_proposals = aes256-sha512-noesn,aes256-sha512,aes256-sha384-noesn,aes256-sha384,aes256-sha256-noesn,aes256-sha256,aes256-sha1-noesn,aes256-sha1,aes128gcm128-sha256-noesn,aes128gcm128-sha256',
f'life_time = {eap_lifetime}s',
f'dpd_action = clear',
f'replay_window = 32',
@@ -1866,7 +1868,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'{conn_name}',
f'remote_addrs = %any',
f'local_addrs = {local_address}',
- f'proposals = aes256-sha512-modp2048,aes256-sha256-modp2048,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048',
+ f'proposals = aes256-sha512-modp2048-noesn,aes256-sha512-modp2048,aes256-sha256-modp2048-noesn,aes256-sha256-modp2048,aes256-sha256-modp1024-noesn,aes256-sha256-modp1024,aes128gcm128-sha256-modp2048-noesn,aes128gcm128-sha256-modp2048',
f'version = 2',
f'send_certreq = no',
f'rekey_time = {ike_lifetime}s',
@@ -1877,7 +1879,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
f'certs = peer1.pem',
f'auth = eap-mschapv2',
f'eap_id = %any',
- f'esp_proposals = aes256-sha512,aes256-sha384,aes256-sha256,aes256-sha1,aes128gcm128-sha256',
+ f'esp_proposals = aes256-sha512-noesn,aes256-sha512,aes256-sha384-noesn,aes256-sha384,aes256-sha256-noesn,aes256-sha256,aes256-sha1-noesn,aes256-sha1,aes128gcm128-sha256-noesn,aes128gcm128-sha256',
f'life_time = {eap_lifetime}s',
f'dpd_action = clear',
f'replay_window = 32',
@@ -1963,6 +1965,82 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
cli_value = default_value(base_path + ['options', 'retransmission', cli_option])
self.assertEqual(config_value, cli_value)
+ def test_esn_settings(self):
+ self.cli_set(base_path + ['ike-group', ike_group, 'key-exchange', 'ikev2'])
+ self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'dh-group', '14'])
+ self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'encryption', 'aes256'])
+ self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'hash', 'sha512'])
+
+ local_address = '192.0.2.10'
+
+ # vpn ipsec auth psk <tag> id <x.x.x.x>
+ self.cli_set(base_path + ['authentication', 'psk', connection_name, 'id', local_id])
+ self.cli_set(base_path + ['authentication', 'psk', connection_name, 'id', remote_id])
+ self.cli_set(base_path + ['authentication', 'psk', connection_name, 'id', local_address])
+ self.cli_set(base_path + ['authentication', 'psk', connection_name, 'id', peer_ip])
+ self.cli_set(base_path + ['authentication', 'psk', connection_name, 'secret', secret])
+
+ # Site to site
+ peer_base_path = base_path + ['site-to-site', 'peer', connection_name]
+
+ self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'encryption', 'aes256'])
+ self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'hash', 'sha512'])
+
+ self.cli_set(peer_base_path + ['authentication', 'mode', 'pre-shared-secret'])
+ self.cli_set(peer_base_path + ['ike-group', ike_group])
+ self.cli_set(peer_base_path + ['default-esp-group', esp_group])
+ self.cli_set(peer_base_path + ['local-address', local_address])
+ self.cli_set(peer_base_path + ['remote-address', peer_ip])
+ self.cli_set(peer_base_path + ['tunnel', '1', 'protocol', 'tcp'])
+ self.cli_set(peer_base_path + ['tunnel', '1', 'local', 'prefix', '172.16.10.0/24'])
+ self.cli_set(peer_base_path + ['tunnel', '1', 'local', 'prefix', '172.16.11.0/24'])
+ self.cli_set(peer_base_path + ['tunnel', '1', 'local', 'port', '443'])
+ self.cli_set(peer_base_path + ['tunnel', '1', 'remote', 'prefix', '172.17.10.0/24'])
+ self.cli_set(peer_base_path + ['tunnel', '1', 'remote', 'prefix', '172.17.11.0/24'])
+ self.cli_set(peer_base_path + ['tunnel', '1', 'remote', 'port', '443'])
+
+ self.cli_set(peer_base_path + ['tunnel', '2', 'local', 'prefix', '10.1.0.0/16'])
+ self.cli_set(peer_base_path + ['tunnel', '2', 'remote', 'prefix', '10.2.0.0/16'])
+
+ # Passing the 'unique = never' for StrongSwan's `connections.<conn>.unique` parameter
+ self.cli_set(base_path + ['disable-uniqreqids'])
+
+ self.cli_commit()
+
+ # esn - default, disabled
+ swanctl_conf = read_file(swanctl_file)
+ swanctl_conf_lines = [
+ f'proposals = aes256-sha512-modp2048-noesn,aes256-sha512-modp2048',
+ f'esp_proposals = aes256-sha512-modp2048-noesn,aes256-sha512-modp2048',
+ ]
+ for line in swanctl_conf_lines:
+ self.assertIn(line, swanctl_conf)
+
+ # esn - optional
+ self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'esn', 'optional'])
+ self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'esn', 'optional'])
+ self.cli_commit()
+
+ swanctl_conf = read_file(swanctl_file)
+ swanctl_conf_lines = [
+ f'proposals = aes256-sha512-modp2048-esn-noesn,aes256-sha512-modp2048',
+ f'esp_proposals = aes256-sha512-modp2048-esn-noesn,aes256-sha512-modp2048',
+ ]
+ for line in swanctl_conf_lines:
+ self.assertIn(line, swanctl_conf)
+
+ # esn - required
+ self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'esn', 'required'])
+ self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'esn', 'required'])
+ self.cli_commit()
+
+ swanctl_conf = read_file(swanctl_file)
+ swanctl_conf_lines = [
+ f'proposals = aes256-sha512-modp2048-esn',
+ f'esp_proposals = aes256-sha512-modp2048-esn',
+ ]
+ for line in swanctl_conf_lines:
+ self.assertIn(line, swanctl_conf)
if __name__ == '__main__':