summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorrockfish-vyos <321823801+rockfish-vyos@users.noreply.github.com>2026-08-31 17:57:40 +0000
committerrockfish-vyos <321823801+rockfish-vyos@users.noreply.github.com>2026-08-31 17:57:40 +0000
commit712c1520f8ebfecf3bc35d9aca21d73d7188f0c2 (patch)
tree4967e21929c5646bbb6e5c3ded99b1bc0f06f83c /python
parentb9fd27b511d22554f294e87e9349456b3418bb2b (diff)
downloadvyos-1x-712c1520f8ebfecf3bc35d9aca21d73d7188f0c2.tar.gz
vyos-1x-712c1520f8ebfecf3bc35d9aca21d73d7188f0c2.zip
ipsec: T9254: do not emit ESN transforms in IKE proposals
get_esp_ike_cipher() renders both IKE_SA proposals and CHILD_SA proposals. It unconditionally appended the -esn / -noesn variants, which are only meaningful for ESP: ESN is Transform Type 5 per RFC 7296 section 3.3.2 and is defined for CHILD_SAs only. Emitting ESN in an IKE_SA proposal breaks interoperability with implementations that reject the malformed payload without replying at all. Observed against a Cisco FTD: the IKE_SA_INIT is silently discarded, no NO_PROPOSAL_CHOSEN and no INVALID_KE_PAYLOAD, so the tunnel never comes up and nothing on the initiator side explains it. Add an explicit esn parameter defaulting to True so ESP behaviour is unchanged, and pass esn=False at the four IKE call sites: peer.j2, profile.j2, remote_access.j2 and l2tp.j2. The five esp_proposals call sites keep ESN. ike_group could have served as the discriminator, since IKE call sites do not pass it, but that coupling is incidental: the argument only exists to resolve PFS. Smoke test assertions on the proposals lines are updated accordingly; the esp_proposals assertions are left untouched.
Diffstat (limited to 'python')
-rwxr-xr-xpython/vyos/template.py21
1 files changed, 16 insertions, 5 deletions
diff --git a/python/vyos/template.py b/python/vyos/template.py
index dbbc4df84..1233710f2 100755
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -483,7 +483,16 @@ def get_first_ike_dh_group(ike_group):
return 'dh-group2' # Fallback on dh-group2
@register_filter('get_esp_ike_cipher')
-def get_esp_ike_cipher(group_config, ike_group=None):
+def get_esp_ike_cipher(group_config, ike_group=None, esn=True):
+ """Render strongSwan proposal strings.
+
+ esn=True : ESP/CHILD_SA proposals, where ESN transforms are meaningful
+ esn=False : IKE_SA proposals. ESN is a CHILD_SA transform (RFC 7296
+ section 3.3.2, Transform Type 5) and has no meaning in an
+ IKE_SA proposal. Emitting it there breaks interoperability
+ with implementations that reject the malformed payload
+ without replying at all (observed with Cisco FTD, T9254).
+ """
pfs_lut = {
'dh-group1' : 'modp768',
'dh-group2' : 'modp1024',
@@ -530,10 +539,12 @@ 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:
+ # ESP/CHILD_SA only. For 'optional' and 'disabled' we need two
+ # values as a proposal without '-esn'/'-noesn' is incompatible
+ # with proposals carrying any of them. This pairing is meaningless
+ # for an IKE_SA, which has no ESN transform at all - see the esn
+ # parameter above.
+ if esn and 'esn' in proposal:
if proposal['esn'] == 'required':
tmp += '-esn'
elif proposal['esn'] == 'optional':