|
| 1 | +// Copyright (c) The go-grpc-middleware Authors. |
| 2 | +// Licensed under the Apache License 2.0. |
| 3 | + |
| 4 | +/* |
| 5 | +Package realip is a middleware that extracts the real IP of requests based on |
| 6 | +header values. |
| 7 | +
|
| 8 | +The real IP is subsequently placed inside the context of each request and can |
| 9 | +be retrieved using the [FromContext] function. |
| 10 | +
|
| 11 | +The middleware is designed to work with gRPC servers serving clients over |
| 12 | +TCP/IP connections. If no headers are found, the middleware will return the |
| 13 | +remote peer address as the real IP. If remote peer address is not a TCP/IP |
| 14 | +address, the middleware will return nil as the real IP. |
| 15 | +
|
| 16 | +Headers provided by clients in the request will be searched for in the order |
| 17 | +of the list provided to the middleware. The first header that contains a valid |
| 18 | +IP address will be used as the real IP. |
| 19 | +
|
| 20 | +Comma separated headers are supported. The last, rightmost, IP address in the |
| 21 | +header will be used as the real IP. |
| 22 | +
|
| 23 | +# Security |
| 24 | +
|
| 25 | +There are 2 main security concerns when deriving the real IP from request |
| 26 | +headers: |
| 27 | +
|
| 28 | + 1. Risk of spoofing the real IP by setting a header value. |
| 29 | + 2. Risk of injecting a header value that causes a denial of service. |
| 30 | +
|
| 31 | +To mitigate the risk of spoofing, the middleware introduces the concept of |
| 32 | +"trusted peers". Trusted peers are defined as a list of IP networks that are |
| 33 | +verified by the gRPC server operator to be trusted. If the peer address is found |
| 34 | +to be within one of the trusted networks, the middleware will attempt to extract |
| 35 | +the real IP from the request headers. If the peer address is not found to be |
| 36 | +within one of the trusted networks, the peer address will be returned as the |
| 37 | +real IP. |
| 38 | +
|
| 39 | +"trusted" in this context means that the peer is configured to overwrite the |
| 40 | +header value with the real IP. This is typically done by a proxy or load |
| 41 | +balancer that is configured to forward the real IP of the client in a header |
| 42 | +value. Alternatively, the peer may be configured to append the real IP to the |
| 43 | +header value. In this case, the middleware will use the last, rightmost, IP |
| 44 | +address in the header as the real IP. Most load balancers, such as NGINX, AWS |
| 45 | +ELB, and Google Cloud Load Balancer, are configured to append the real IP to |
| 46 | +the header value as their default action. |
| 47 | +
|
| 48 | +To mitigate the risk of a denial of service by proxy of a malicious header, |
| 49 | +the middleware validates that the header value contains a valid IP address. Only |
| 50 | +if a valid IP address is found will the middleware use that value as the real |
| 51 | +IP. |
| 52 | +
|
| 53 | +# Individual IP addresses as trusted peers |
| 54 | +
|
| 55 | +When creating the list of trusted peers, it is possible to specify individual IP |
| 56 | +addresses. This is useful when your proxy or load balancer has a set of |
| 57 | +well-known addresses. |
| 58 | +
|
| 59 | +The following example shows how to specify individual IP addresses as trusted |
| 60 | +peers: |
| 61 | +
|
| 62 | + trusted := []net.IPNet{ |
| 63 | + {IP: net.IPv4(192, 168, 0, 1), Mask: net.IPv4Mask(255, 255, 255, 255)}, |
| 64 | + {IP: net.IPv4(192, 168, 0, 2), Mask: net.IPv4Mask(255, 255, 255, 255)}, |
| 65 | + } |
| 66 | +
|
| 67 | +In the above example, the middleware will only attempt to extract the real IP |
| 68 | +from the request headers if the peer address is either 192.168.0.1 or |
| 69 | +192.168.0.2. |
| 70 | +
|
| 71 | +# Headers |
| 72 | +
|
| 73 | +Headers to search for are specified as a list of strings when creating the |
| 74 | +middleware. The middleware will search for the headers in the order specified |
| 75 | +and use the first header that contains a valid IP address as the real IP. |
| 76 | +
|
| 77 | +The following are examples of headers that may contain the real IP: |
| 78 | +
|
| 79 | + - X-Forwarded-For: This header is set by proxies and contains a comma |
| 80 | + separated list of IP addresses. Each proxy that forwards the request will |
| 81 | + append the real IP to the header value. |
| 82 | + - X-Real-IP: This header is set by NGINX and contains the real IP as a string |
| 83 | + containing a single IP address. |
| 84 | + - Forwarded-For: Header defined by RFC7239. This header is set by proxies and |
| 85 | + contains the real IP as a string containing a single IP address. Please note |
| 86 | + that the obfuscated identifier from section 6.3 of RFC7239, and that the |
| 87 | + unknown identifier from section 6.2 of RFC7239 are not supported. |
| 88 | + - True-Client-IP: This header is set by Cloudflare and contains the real IP |
| 89 | + as a string containing a single IP address. |
| 90 | +
|
| 91 | +# Usage |
| 92 | +
|
| 93 | +Please see examples for simple examples of use. |
| 94 | +*/ |
| 95 | +package realip |
0 commit comments