Skip to content

Instantly share code, notes, and snippets.

@pablitoc
Last active April 12, 2023 15:21
Show Gist options
  • Star 44 You must be signed in to star a gist
  • Fork 23 You must be signed in to fork a gist
  • Save pablitoc/91c40d820f207879969c to your computer and use it in GitHub Desktop.
Save pablitoc/91c40d820f207879969c to your computer and use it in GitHub Desktop.
Configuring Proxy Protocol

##Install AWS CLI Tools##

  1. Install AWS CLI Tools. You can also use the EC2 API Tool if you are more comfortable with them. But this write-up uses the EC2 CLI.
  2. Create a user via Amazon IAM or download the security accessID and securitykey you will need it to query Amazon CLI.
  3. using Terminal cd into .aws directory cd ~/.aws edit or create new file named config paste the following contents inside.
    `[default]`
    `aws_access_key_id = ACCESS_ID`
    `aws_secret_access_key = SECRET_ID`
    `output = json OR bson OR text`
    `region = PREFERRED_AWS_REGION`

Save the file as "config" 4. Once that is in place you can use the CLI. Please read AWS CLI Documentation for info other than configuring an ELB policy

##Configuring AWS ELB Policy for Proxy Protocol##

By default, when you use Transmission Control Protocol (TCP) or Secure Sockets Layer (SSL) for both front-end and back-end connections, your load balancer forwards the request to the back-end instances without modifying the request headers. If you enable Proxy Protocol, a human-readable header gets prepended to the request header with connection information such as the source IP address, destination IP address, and port numbers. The header is then sent to the back-end instance as part of the request.

Proxy Protocol is an Internet protocol used for carrying connection information from the source requesting the connection to the destination for which the connection was requested. Elastic Load Balancing uses Proxy Protocol version 1, which uses a human-readable header format.

Proxy Protocol can only be enabled on ports using either SSL or TCP protocols. You can use Proxy Protocol to capture your client’s source IP when you are using a non-HTTP protocol, or when you are using HTTPS and not terminating the SSL connection on your load balancer.

[For more information on AWS Proxy Protocol](http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html)

The following diagrams illustrate the incorrect and correct configurations for enabling Proxy Protocol when you have a proxy server in front of your load balancer.

1.Query AWS for the current applied policies to a created LB with the following command

A. aws elb describe-load-balancers --load-balancer-name NAME_OF_ELB. This command will show you all the policies and options that are enabled on the named ELB
B. If you are Unsure of the name of the ELB you want to change you can always use ``aws elb describe-load-balancers. This command will list all of your ELB's and their policies.</dd> 2. Once you are sure you have the correct ELB you will need to create the Proxy Protocol Policy with the following command: <dd>aws elb create-load-balancer-policy --load-balancer-name NAME_OF_ELB --policy-name EnableProxyProtocol --policy-type-name ProxyProtocolPolicyType --policy-attributes AttributeName=ProxyProtocol,AttributeValue=True`.
This command creates a policy, names it "EnableProxyProtocol" and assigns the following ELB attributes "AttributeName=ProxyProtocol & AttributeValue=True"
3. Now that you have created the policy you will need to apply it to the ELB or ELB's. You can do so with the following:

A.`aws elb set-load-balancer-policies-for-backend-server --load-balancer-name NAME_OF_ELB --instance-port 80 --policy-names EnableProxyProtocol`. This will enable your created policy on the listener of port 80 if you would like to enable proxy protocol on another port just change the flag `--instance-port` from 80 to the port you wish.
4. If you need to disable the policy just run the following command:
`aws elb set-load-balancer-policies-for-backend-server --load-balancer-name nci-qa --instance-port 80 --policy-names "[]"`

##Configuring NGINX to accept headers from Proxy Protocol## Nginx has many use cases that use Proxy protocol headers. Our use case for this feature is mainly being able to log IP address' from client connections after they are forwarded from the ELB. Without this feature we get the ELB internal IP address.

Below you will see an example that takes the header infomartion and passes it trough to the application logging. Configured this way NGINX is used as a reverse proxy that takes Internet traffic and retrieves resources on behalf of a client from the application servers.

EG.

server {
    listen 80 proxy_protocol;
    listen 443 proxy_protocol ssl;
...
	location @app-name {
      proxy_pass            http://app-name;
      proxy_redirect        default;

      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header  Host                $host;
      proxy_set_header  X-Real-IP           $proxy_protocol_addr;
      proxy_set_header  X-Forwarded-For     $proxy_add_x_forwarded_for;
      proxy_set_header  X-Forwarded-Proto   tcp;
      proxy_set_header  X-NginX-Proxy       true;
...
}

The first thing that happends is nginx accepts proxy protocol headers on both port 80 and 443.

	server {
        listen 80 proxy_protocol;
        listen 443 proxy_protocol ssl;

Secondly, X-Real-IP gets assigned the client IP address from the variable $proxy_protocol_addr which gets handed off from the ELB.

	proxy_set_header  X-Real-IP           $proxy_protocol_addr;

One thing to note is that the X-Forwarded-Proto was changed from a traditional $scheme to a fixed tcp.This is because we want the entire tcp header from the client instead of just the http portion which is formatted differently.

	proxy_set_header  X-Forwarded-Proto   tcp;
@ggrandes
Copy link

Wonder! I made a module for Apache for support PROXY protocol, mod_myfixip.

@fabioce
Copy link

fabioce commented Sep 15, 2015

Is possible to make the same thing with apache?
For example with mod_proxy?
Thanks

@okram999
Copy link

What happens when you do this to a node thats behind the ELB?
openssl s_client -connect node_name:443

Do you see the credentials exchange?

@rozhok
Copy link

rozhok commented Jul 13, 2016

@okram999: for sure. I've configured mutual TLS for instance behind ELB using this (and also other) guide.

@dbarria
Copy link

dbarria commented Feb 8, 2017

Amazing!! Thank you!

If you were using HTTP Protocol as ELB listener, don't forget to change Ping protocol Heal Check to TCP and port number 80. In other case nothing will work.

@matas-vaitkevicius
Copy link

Hi does anyone have PROXY v2 request captured in fiddler by any chance? I need one for integration testing, would be much obliged...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment