Home Resume
Homeβ€Ί Blogβ€Ί AWS Daily Intelligence #3 - RFC 9151 CNSA 1.0 TLS …
AWS Daily Intelligence AWS

RFC 9151 CNSA 1.0 TLS Policies on ALB and NLB: Compliance at the Front Door Only

Application and Network Load Balancers now offer TLS security policies implementing the NSA's Commercial National Security Algorithm suite. Seven policies, a deliberate migration ladder, and one behaviour that will quietly undermine anyone who assumes selecting the strict policy makes their path end-to-end compliant.

AWS Daily Intelligence Β· 5 August 2026

Executive summary

On 4 August 2026, AWS announced RFC 9151 compliant TLS security policies for Application Load Balancers and Network Load Balancers. RFC 9151 defines how to use the Commercial National Security Algorithm (CNSA) 1.0 suite, specified by the US National Security Agency, with TLS 1.2 and TLS 1.3.

There are seven policies, split into two categories. Strict policies enforce RFC 9151 cipher and signature requirements outright. Interop policies β€” the four with INTEROP in the name β€” accept both RFC 9151 and non-compliant algorithms so you can migrate without dropping clients mid-transition.

Available in all commercial Regions, the GovCloud (US) Regions, and the China Regions, at no additional cost.

The detail that matters most is not in the announcement. When you select any RFC 9151 policy on a listener, the load balancer uses ELBSecurityPolicy-TLS13-1-2-RFC9151-INTEROP4-FIPS-2023-07 for backend connections to your targets β€” regardless of which policy you chose. AWS states plainly that it cannot guarantee or enforce RFC 9151 compliance on egress connections. Choosing the strictest front-door policy does not give you an end-to-end CNSA path, and if your targets only speak TLS 1.0 or 1.1, those connections will fail.

What changed

Elastic Load Balancing negotiates TLS using a security policy: a named combination of protocol versions and cipher suites. The change adds seven policies built to RFC 9151. Every one of them is also a FIPS policy.

The strict policies

PolicyTLS 1.3TLS 1.2Ciphers
ELBSecurityPolicy-TLS13-1-3-RFC9151-FIPS-2023-07YesNo1 β€” TLS_AES_256_GCM_SHA384
ELBSecurityPolicy-TLS13-1-2-RFC9151-FIPS-2023-07YesYes3
ELBSecurityPolicy-TLS13-1-2-Ext0-RFC9151-FIPS-2023-07YesYes4 β€” adds a non-ECDHE cipher

The TLS 1.3-only policy is as narrow as AWS ships: a single cipher suite. The TLS 1.2 variant adds ECDHE-ECDSA-AES256-GCM-SHA384 and ECDHE-RSA-AES256-GCM-SHA384.

The Ext0 variant deserves a flag. It adds AES256-GCM-SHA384, which is not an ECDHE cipher and therefore does not provide forward secrecy. It exists for legacy clients that cannot do ephemeral key exchange. Reaching for it because it is "the one with the most options among the strict policies" would be a mistake.

The interop policies

Four policies widen the accepted set progressively, so you can put CNSA algorithms first while still serving clients that cannot negotiate them yet.

PolicyCiphersWhat it adds
...RFC9151-INTEROP1-FIPS-2023-076AES-128 GCM alongside AES-256 GCM
...RFC9151-INTEROP2-FIPS-2023-0710CBC ciphers with SHA-256 and SHA-384
...RFC9151-INTEROP3-FIPS-2023-07broaderECDHE ciphers using SHA-1
...RFC9151-INTEROP4-FIPS-2023-07broadestAWS-recommended starting point

AWS explicitly recommends starting with INTEROP4, which serves clients negotiating classical TLS 1.3, TLS 1.2, or strict RFC 9151, then tightening as your client population proves it can cope.

Why AWS added these policies

Because compliance regimes name algorithms, and until now meeting CNSA 1.0 at the edge meant not terminating TLS on a managed load balancer.

If a contract or accreditation requires CNSA 1.0, the previous options were all poor:

  • Terminate TLS on your own fleet. Run NGINX or HAProxy on EC2 with a hand-built cipher string, and take on patching, key management, and scaling β€” to control one configuration line.
  • Pass TLS through the load balancer. Use an NLB in TCP passthrough and terminate on the instance. Workable, but you lose the ALB's HTTP-layer routing, WAF integration, and header handling.
  • Pick the closest existing policy and write a justification. Choose a restrictive non-CNSA policy and argue equivalence in an audit. Common, and unpleasant, because the argument has to be made again every review cycle.
  • Keep the workload off AWS. The answer nobody writes down.

Naming the policy after the RFC changes the audit conversation from an argument about cipher equivalence into a configuration value someone can read. That is the real value, and it is worth more than the cryptography itself.

Architecture

The model to hold: a security policy governs the connection between the client and the load balancer. It is not a property of the request path. The load balancer opens a separate TLS connection to your targets, and that connection has its own policy which you do not choose.

Diagram: an RFC 9151 policy applies to the listener, where you choose one of seven policies, while backend connections to targets always use the INTEROP4 policy regardless of that choice. Targets supporting only TLS 1.0 or 1.1 will fail. A ladder shows the seven policies ordered from broadest interoperability to strictest compliance.

The migration ladder is the design

The interop policies are not a convenience. They are the intended migration path, and the reason this launch is usable rather than merely available.

A strict CNSA policy accepts one or three cipher suites. Any client that cannot negotiate them does not get a degraded connection β€” it gets no connection. For a public endpoint with an unknown client population, switching straight to a strict policy is indistinguishable from an outage for some fraction of users, and you will not know which fraction in advance.

The ladder inverts that risk. Start at INTEROP4, which is permissive. CNSA-capable clients negotiate CNSA algorithms immediately, because the server presents its list in preference order. Everyone else keeps working. You then use connection logs to observe what clients actually negotiate, and tighten one rung at a time.

This is the same pattern as the catch-all rule in a firewall ruleset: make the permissive case explicit first, then narrow with evidence.

Observation is built in

ALB connection logs carry tls_protocol, tls_cipher, and tls_keyexchange fields. Those three tell you exactly what your clients negotiate today, which converts "can we tighten this policy?" from a debate into a query. Enable connection logging before you change the policy, not after.

Business value

Managed load balancing becomes available to CNSA-bound workloads. The largest win. Teams that ran self-managed TLS termination purely to control ciphers can move to ALB or NLB and delete a fleet.

The compliance claim becomes a configuration value. "The listener uses ELBSecurityPolicy-TLS13-1-2-RFC9151-FIPS-2023-07" is a fact an auditor can verify with one API call. It replaces a written argument that had to be re-made each cycle.

Migration without an outage. The interop ladder means adopting CNSA is a staged rollout with observable checkpoints rather than a cutover with a rollback plan.

Available where regulated workloads live. Commercial, GovCloud (US), and China Regions, at no additional cost β€” so there is no cost case to build and no Region-availability caveat to work around.

Security considerations

The strict policy does not make your path compliant end to end. Selecting any RFC 9151 policy pins backend connections to INTEROP4, the most permissive of the set. AWS states it cannot guarantee or enforce RFC 9151 compliance on egress connections, including to targets and to customer-configured external services such as third-party identity providers or authentication endpoints. If your compliance claim covers the whole path, the load balancer configuration alone does not substantiate it.

Forward secrecy is not implied by strictness. The Ext0 policy is an RFC 9151 policy that includes a non-ECDHE cipher. Do not treat "RFC 9151" in the name as a guarantee of ephemeral key exchange β€” check the cipher list.

Interop policies accept weak-adjacent algorithms by design. INTEROP3 admits ECDHE ciphers using SHA-1. That is the point β€” it is a transition tool β€” but a policy chosen for migration and then left in place for two years is a finding waiting to be written. Put an expiry date on it when you set it.

Target-side compliance is your work. For strict RFC 9151 between the load balancer and targets, the targets need RFC 9151-compliant certificates and ciphers. That is a change to your instances or containers, not to the load balancer.

Changing the policy is a security-relevant action. Whoever can call ModifyListener can loosen the negotiated cipher set for every client, silently and instantly. Treat it as a reviewable change, not routine load balancer configuration.

Cost considerations

The policies are free. AWS states no additional cost, in all commercial Regions, GovCloud (US), and China. There is no per-policy or per-connection premium, and no pricing page to model.

The costs are indirect, and mostly favourable. The clearest saving is deleting a self-managed TLS termination tier: the instances, their patching, their certificates, and the on-call attached to them.

Two second-order effects worth noting. Restricting to AES-256 and SHA-384 shifts a little CPU cost onto targets and clients relative to AES-128, though at load balancer scale this is not usually observable. And enabling connection logging β€” which you should, to drive the migration β€” writes to S3 and carries normal storage and request charges. Budget for the logs, not for the policy.

The real cost is client attrition, if you skip the ladder. Jumping to a strict policy on a public endpoint and losing a percentage of clients is a revenue event, not an infrastructure one. It does not appear on the AWS bill at all, which is exactly why it deserves naming in the cost section.

Operational considerations

The default policy depends on how the listener was created. An HTTPS listener created in the console defaults to ELBSecurityPolicy-TLS13-1-2-Res-PQ-2025-09. One created by the AWS CLI, CloudFormation, or the CDK defaults to ELBSecurityPolicy-2016-08. If your listeners come from infrastructure as code β€” and they should β€” the ones you never set a policy on are running a 2016 default, not a modern one. This is worth auditing across the estate regardless of whether CNSA applies to you.

Enable connection logging first. Without tls_protocol, tls_cipher, and tls_keyexchange you are tightening the policy on faith. Collect a full traffic cycle β€” including whatever weekly or monthly batch integrations exist β€” before moving a rung.

Check targets before switching. If any target only supports TLS 1.0 or 1.1, connections will fail once an RFC 9151 policy is in place, because the backend policy does not permit them. Verify target-side protocol support first; this is the most likely way to cause an incident with this change.

Policy changes take effect on new connections. Long-lived connections persist, so the blast radius appears gradually rather than at the moment of the change. That delay makes the change feel safer than it is β€” hold the observation window open well past the deploy.

Pin the policy explicitly in IaC. Never rely on the default. An explicit policy name in the template is the artifact your auditor reads and your future colleague trusts.

Tradeoffs

Strict versus interop. The real decision. Strict gives a clean compliance statement and refuses non-compliant clients. Interop keeps everyone connected and makes the statement conditional. If you control every client β€” internal service, known partners, managed devices β€” go strict. If the endpoint is public, start interop and earn your way across.

TLS 1.3-only versus TLS 1.2 and 1.3. The 1.3-only policy is the strongest posture available and the least forgiving: one cipher suite, and anything without TLS 1.3 is refused. Excellent for a modern internal API, wrong for anything with legacy consumers.

Against terminating TLS yourself. Self-management gives complete control of the cipher string, including on the backend leg where the load balancer gives you none. If your requirement is genuinely end-to-end CNSA with no exceptions, self-managed termination remains the only way to guarantee it. You pay for that in fleet, patching, and scaling.

Against a general-purpose restrictive policy. If you have no CNSA obligation, a policy such as ELBSecurityPolicy-TLS13-1-2-Res-PQ-2025-09 is likely the better default β€” it is modern, includes post-quantum key exchange, and does not restrict you to a small cipher set for a standard you are not being audited against. Adopt RFC 9151 because you must, not because it sounds stronger.

Implementation guidance

Prerequisites

  • An ALB or NLB with a TLS-terminating listener.
  • Connection logging enabled, with at least one full traffic cycle captured.
  • Target-side protocol support confirmed as TLS 1.2 or higher.
  • For strict end-to-end compliance, RFC 9151-compliant certificates and ciphers on the targets.
  • An inventory of which listeners were created by IaC and are therefore on the ELBSecurityPolicy-2016-08 default.

Inspect the policies before choosing one

List every RFC 9151 policy available to you:

aws elbv2 describe-ssl-policies \
    --query "SslPolicies[?contains(Name,'RFC9151')].Name"

Read the exact protocols and ciphers of a specific policy rather than trusting a summary:

aws elbv2 describe-ssl-policies \
    --names "ELBSecurityPolicy-TLS13-1-2-RFC9151-INTEROP4-FIPS-2023-07"

Find every policy supporting a given cipher, which is useful when a compliance document names algorithms rather than policies:

aws elbv2 describe-ssl-policies \
    --query "SslPolicies[?Ciphers[?contains(Name,'TLS_AES_256_GCM_SHA384')]].Name"

Move one rung

Apply the recommended starting policy:

aws elbv2 modify-listener \
    --listener-arn arn:aws:elasticloadbalancing:us-east-1:111122223333:listener/app/my-lb/50dc6c495c0c9188/f2f7dc8efc522ab2 \
    --ssl-policy ELBSecurityPolicy-TLS13-1-2-RFC9151-INTEROP4-FIPS-2023-07

Then watch tls_cipher and tls_protocol in connection logs across a full cycle. When no client is relying on the algorithms the next rung removes, tighten and repeat.

Do not skip to the strict policy on a public endpoint. The strict TLS 1.3 policy accepts exactly one cipher suite. Clients that cannot negotiate it are refused outright β€” there is no downgrade and no warning. On an endpoint with an unknown client population, that is an outage for an unknown fraction of users, discovered from their side rather than yours.

Best practices

  1. Start at INTEROP4, as AWS recommends, then tighten with evidence.
  2. Enable connection logging before changing anything and use tls_protocol, tls_cipher, tls_keyexchange to drive each step.
  3. Audit listeners created by IaC for the ELBSecurityPolicy-2016-08 default, whether or not CNSA applies to you.
  4. Always set the policy explicitly in templates. Never inherit a default.
  5. Verify target TLS support before switching. TLS 1.0 and 1.1 targets will fail.
  6. Do not read Ext0 as stronger. It trades forward secrecy for legacy compatibility.
  7. Put an expiry date on any interop policy when you set it, so a migration tool does not become permanent configuration.
  8. State the backend limitation in your compliance documentation rather than letting a reviewer discover it.

Who should adopt, who should wait

Adopt

  • Workloads with a stated CNSA 1.0 or RFC 9151 obligation β€” federal, defence, and their supply chains.
  • Teams running self-managed TLS termination purely to control ciphers. This is the case for deleting that tier.
  • GovCloud and China Region workloads, where the policies are available at no cost.
  • Anyone who argued cipher equivalence in an audit and would rather cite a policy name.

Wait

  • Teams with no CNSA obligation. A modern general-purpose policy with post-quantum key exchange is probably the better default.
  • Public endpoints without connection logging. You cannot migrate safely blind.
  • Anyone whose targets are on TLS 1.0 or 1.1. Fix the targets first; the load balancer change will fail against them.
  • Teams needing guaranteed end-to-end CNSA. The backend leg is pinned to an interop policy and AWS does not guarantee compliance on it.

The behaviour that breaks the compliance story

This deserves its own section because it is the difference between a defensible compliance claim and one that collapses under a competent question.

When you select an RFC 9151 security policy on a listener, the load balancer uses ELBSecurityPolicy-TLS13-1-2-RFC9151-INTEROP4-FIPS-2023-07 for backend connections to targets and other services β€” no matter which of the seven you chose. AWS states it cannot guarantee or enforce RFC 9151 compliance on egress connections, including to targets and to customer-configured external services such as third-party identity providers or authentication endpoints.

The intuitive reading of "I set the strict CNSA policy on my load balancer" is that CNSA now governs traffic through it. It does not. It governs the client-facing half. The other half runs on the most permissive policy in the family, and AWS is explicit that compliance there is not something it will assert.

Three consequences follow.

Your compliance evidence needs two halves. The listener policy covers ingress. Target-side certificates and cipher configuration cover egress, and that evidence comes from your instances or containers, not from an ELB API call. Document both, and say which is which.

External service calls are in scope and easy to forget. ALB authentication actions that call an external identity provider go out over that same uncontrolled egress path. If your architecture uses OIDC authentication at the load balancer, that connection is inside your compliance boundary and outside AWS's assurance.

TLS 1.0 and 1.1 targets stop working. Not degraded β€” failed. The backend policy does not include those protocols, so any target that cannot do TLS 1.2 or better drops out the moment the listener policy changes. This is the most likely way this launch causes an incident, and it is entirely preventable by checking targets first.

None of this makes the feature less useful. It makes the claim narrower than the name suggests, and narrow claims that survive scrutiny are worth more than broad ones that do not.

Key takeaways

  1. Seven RFC 9151 policies for ALB and NLB: three strict, four interop. All are FIPS policies.
  2. GA in all commercial Regions, GovCloud (US), and China, at no additional cost.
  3. Backend connections always use INTEROP4 regardless of the listener policy, and AWS does not guarantee RFC 9151 compliance on egress.
  4. Targets on TLS 1.0 or 1.1 will fail once an RFC 9151 policy is applied.
  5. AWS recommends starting at INTEROP4 and tightening as clients prove capability.
  6. The strict TLS 1.3 policy accepts one cipher suite. There is no downgrade path for clients that cannot negotiate it.
  7. Ext0 is an RFC 9151 policy that includes a non-ECDHE cipher, so it does not provide forward secrecy.
  8. Connection log fields tls_protocol, tls_cipher, and tls_keyexchange are how you drive the migration safely.
  9. Console-created HTTPS listeners default to ELBSecurityPolicy-TLS13-1-2-Res-PQ-2025-09; CLI, CloudFormation and CDK default to ELBSecurityPolicy-2016-08. Audit this regardless of CNSA.

Comments

How was your experience?
Your feedback helps improve this site.
PoorExcellent