-
Notifications
You must be signed in to change notification settings - Fork 729
Add support for the PROXY protocol #581
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
When there is a proxy in front of tinyproxy, the latter does not see the actual IP address of the client. This is a problem when using tools like fail2ban that parse the tinyproxy log to find and ban clients that try to break the authentication using brute force. Some proxies like stunnel or HAProxy support the PROXY protocol to overcome that issue, so that the next proxy in the chain can tell what the IP address of the original client is. See https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt This commit adds support for clients that use the PROXY protocol to extract the real client IP address and report it in the logs. This is only implemented when the new ClientUsesProxyProtocol parameter is set to Yes. It should only be enabled when the client is trusted and known to be a proxy that support that protocol.
reading the document, it appears the protocol is widely enough supported so it may make sense to support it too. however, some questions arise:
as for the implementation presented:
also it needs to be documented that only v1 of the protocol is supported. |
My main goal was the authentication failure log message, so I didn't think about the other things like ACL. What do you think of applying these changes:
I'm not sure it is useful to update the client port too. Is it ever used anywhere in the code? I agree with the remarks about the implementation and will change it accordingly. |
Reading the PROXY line is the first thing done in handle_connection() so that the client IP address is updated before it is needed by the rest of the code (ACL, logging, etc.). The parsing implementation is now less generic and updates the sockaddr_union structure directly.
goto cleanup; | ||
} | ||
|
||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think the entire chomp block here is unneeded
|
||
# | ||
# The tinyproxy's client is a proxy that uses the PROXY protocol, which | ||
# inserts a line before the HTTP request line to indicates the IP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/indicates/indicate/ , same for the manpage
|
||
/* Only extract the source address string */ | ||
src_addr = line + 11; | ||
end = strchr (src_addr, ' '); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should check that end isn't NULL, else a malformed proxy line will crash the service
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, I was sure strchr()
would return a pointer to the NUL character in this case, but was wrong.
goto cleanup; | ||
} | ||
|
||
is_ipv6 = line[9] == '6' ? TRUE : FALSE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the use of the ternary here is redundant, is_ipv6 = line[9] == '6';
is doing the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, might as well make that af = line[9] == '6' ? AF_INET6 : AF_INET;
and use af further down to fill in the address family and for the inet_pton call.
*end = '\0'; | ||
|
||
/* Update "addr" with the given address */ | ||
if (is_ipv6) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the addr pointer coming is already zero-initialized so we could just unconditionally set addr->v4.sin_family to af
as per my previous comment and call inet_pton with af and a ternary which sets pointer to either &addr->v6.sin6_addr
or &addr->v4.sin_addr
. there is actually a macro in sock.h doing just that: SOCKADDR_UNION_ADDRESS
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and we should add a comment to the func signature that addr needs to be zero-initialized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addr
already stores the port and address of the other peer when read_proxy_line()
is called, so it is not zero-initialized. Also, if the client proxy connects using IPv4 but the final client uses IPv6, then sin6_flowinfo
will contain the proxy IPv4 address (sin_addr
and sin6_flowinfo
are located at the same offset), not 0.
On the other hand, tinyproxy only uses the family and address fields from sockaddr_union it seems, so it does not really matter if the other fields are wrong?
I'll make the changes for the other remarks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in that case we can just memset it to all zeroes unconditionally.
When there is a proxy in front of tinyproxy, the latter does not see the actual IP address of the client. This is a problem when using tools like fail2ban that parse the tinyproxy log to find and ban clients that try to break the authentication using brute force. Some proxies like stunnel or HAProxy support the PROXY protocol to overcome that issue, so that the next proxy in the chain can tell what the IP address of the original client is.
See https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
This commit adds support for clients that use the PROXY protocol to extract the real client IP address and report it in the logs. This is only implemented when the new ClientUsesProxyProtocol parameter is set to Yes. It should only be enabled when the client is trusted and known to be a proxy that support that protocol.