How does client IP preservation on an AWS Network Load Balancer change what a registered target sees as the source address, and what two things does turning it on commonly break?
answer
- source address is not rewritten
- target sees the client, not the LB
- health checks still come from the LB
- the caller that is also a target
- Proxy Protocol v2 when you turn it off
basics
~20 sWith client IP preservation, an NLB forwards packets with the original client address intact, so targets see real client IPs rather than the load balancer's. That breaks security groups written for load balancer CIDRs, and same-VPC callers that are also registered targets.
solid answer
~50 sNLB does not rewrite the source address when client IP preservation is on, so the target's socket reports the actual client IP — no `X-Forwarded-For` needed. It is controlled by the target group attribute `preserve_client_ip.enabled`, and the default depends on the target type: on for `instance` targets, off by default for `ip` targets with TCP and TLS, and always on for UDP. Two things break. First, **security groups**: the target's inbound rules must allow the client CIDRs, not the load balancer's subnets, so a rule copied from an ALB setup drops everything while health checks — which come from the NLB node addresses — still pass. Second, the **hairpin case**: an instance in the VPC that calls the NLB and is itself a registered target can receive a packet whose source is its own address, and the connection hangs. Disabling preservation, or using Proxy Protocol v2 to carry the client address, fixes both.
go deeper
Know that an NLB can pass the client's real IP straight through, so the target's logs show client addresses without any forwarding header being involved.
Explain the mechanism and the attribute: preserve_client_ip.enabled on the target group, defaults that differ by target type, and Proxy Protocol v2 as the way to carry the address when preservation is off.
Diagnose the production signature — targets healthy, traffic failing — by reasoning about which source address each kind of packet carries, and know the hairpin failure for a caller that is also a registered target.
Set the convention across the platform: decide once whether services identify clients by preserved source IP, Proxy Protocol, or a layer-7 header, because audit logging, rate limiting and network policy all depend on that answer being uniform.
## What preservation actually does A layer-7 proxy terminates the client's connection and opens a new one to the target, so the target always sees the proxy's address and learns the client's address from a header. A Network Load Balancer works differently: when client IP preservation is enabled it rewrites only the destination, leaving the source address untouched. The target's own TCP stack reports the real client IP. Nothing needs to parse a header, which is why NLB is attractive for protocols that have no header to put an address into. The behaviour is a target group attribute, `preserve_client_ip.enabled`, and the default depends on the target type: - `instance` targets: enabled by default. - `ip` targets with TCP or TLS: disabled by default, so the target sees the NLB node's address in the subnet. - UDP and TCP_UDP traffic: preservation applies and is not something you turn off. The important interview point is not memorising the matrix but knowing that **the default is not uniform**, so "what does my target see?" is a question you answer by looking at the target group, not by assuming. ```bash aws elbv2 modify-target-group-attributes \ --target-group-arn arn:aws:elasticloadbalancing:eu-west-1:111122223333:targetgroup/app/abc \ --attributes Key=preserve_client_ip.enabled,Value=false ``` ## Breakage one: security groups written for a load balancer This is the classic incident. A team moves a service from an ALB to an NLB and keeps the target's security group rule, which allows the load balancer's security group or the load balancer subnets' CIDRs. With preservation on, forwarded packets arrive carrying the *client's* address, which matches none of those rules, and every real request is dropped. What makes it genuinely confusing is that the target still shows as healthy. Health-check probes originate from the NLB node addresses inside your subnets, so a rule allowing the load balancer subnets keeps health checks passing while all customer traffic is silently discarded. "Healthy target, zero successful requests" is the signature of this bug. The fix is to write the target's inbound rules for the actual client population: the internet for a public service, a peered CIDR for an internal one, or a specific partner range. Since NLBs can also carry their own security groups (for load balancers created with them), the modern pattern is to put the coarse controls on the NLB's security group and keep the target's rules aligned with whatever the target really sees. ## Breakage two: the hairpin If an instance inside the VPC connects to the NLB and that same instance is a registered target, the flow can be balanced back to itself. With preservation on, the packet arrives at the instance with a source address equal to its own address and a destination equal to its own address. The stack does not treat that as a valid inbound connection, and the client sees a hang rather than a clean refusal. The same class of problem appears when a target reaches a service through the NLB it is registered behind. The robust fixes are architectural rather than clever: don't route intra-VPC calls through the public path, split the caller and the target into separate target groups or separate load balancers, or disable preservation on that target group. ## When you disable it, how do you keep the client address? Turn on the target group attribute `proxy_protocol_v2.enabled`. The NLB then prefixes each connection with a Proxy Protocol v2 header carrying the original source and destination. The target application must understand it — nginx, HAProxy and many language runtimes do — and this is the catch: a server that does not expect the header will read those binary bytes as if they were the first bytes of the protocol and fail immediately. Proxy Protocol is all-or-nothing per target group, so enabling it and the listening software must be changed together. ## How to answer it in an interview State the mechanism first ("NLB does not rewrite the source; the target sees the client"), then the consequence ("so security groups must be written for clients, not for the load balancer"), then the two failure signatures — healthy-but-unreachable targets and hairpinned same-instance flows — and finish with the two ways to convey the client address when you cannot preserve it: Proxy Protocol v2 at layer 4, or a layer-7 proxy that adds a forwarding header.
- Targets are marked healthy but no customer request succeeds. Where do you look first?At the target's security group. Health probes originate from the NLB node addresses in your subnets, so a rule allowing the load balancer's subnets keeps targets healthy, while forwarded client traffic arrives with the client's own source address and matches nothing. Compare the rule against the real client CIDRs before suspecting the application.
- If you disable client IP preservation, how does the application still learn who the client was?Enable the target group attribute `proxy_protocol_v2.enabled`. NLB then prepends a Proxy Protocol v2 header carrying the original source and destination to each connection. The listening software must be configured to parse it — nginx, HAProxy and most proxies can — otherwise it reads the header bytes as protocol data and the connection fails immediately.
- Does client IP preservation behave the same for every target type?No, and assuming so is a common source of surprise. It is on by default for `instance` targets, off by default for `ip` targets on TCP and TLS, and applies to UDP traffic regardless. Check the target group attribute rather than inferring from a previous setup, because the same NLB can front target groups that behave differently.
saying these in an interview costs you the question
- Expects the target to read X-Forwarded-For from an NLB
- Allows only the load balancer subnets on the target's security group
- Assumes preservation defaults are the same for all target types
- Enables Proxy Protocol without changing the server to parse it
- Says healthy health checks prove the network path is correct