Bug #2826
closedstale REMOTE_ADDR when using AF_UNIX socket
Description
It appears lighttpd v1.4.45 returns a bogus (stale) IP address for CGI requests received via an AF_UNIX socket. From what I can tell, REMOTE_ADDR gets set to the value last used with a non-AF_UNIX socket.
The attached patch fixes the problem by setting REMOTE_ADDR to an empty string for the AF_UNIX case. However, I don't think it's the proper way to solve it. I see inet_ntop_cache.c has changed quite a bit since v1.4.45 and it now handles AF_UNIX for more cases but it looks to me like inet_ntop_cache_get_ip() still has the same issue. Perhaps it should be updated to return sun_path for the AF_UNIX case?
Files
Updated by davidm about 7 years ago
Perhaps this is a better fix. According to RFC3875:
The REMOTE_ADDR variable MUST be set to the network address of the client sending the request to the server.
It then defines the syntax of the REMOTE_ADDR value as being either an IPv4 or IPv6 address.
Returning the loopback address may be the best we can do here?
Updated by gstrauss about 7 years ago
Do you think this is still an issue in lighttpd git master? CGI gets REMOTE_ADDR from con->dst_addr_buf, which will be "" for AF_UNIX with current behavior of inet_ntop_cache_get_ip(). Maybe sun_path should be returned for AF_UNIX (as you first suggested), since con->dst_addr_buf is used in many places, not just for the CGI environment. (As an aside, there is a bug if the OS is so old that inet_ntop() is not available to lighttpd.)
Regarding the language in RFC3875, if you are using lighttpd with AF_UNIX sockets, and you need a valid REMOTE_ADDR, you are probably proxying, and so you can use mod_extforward to have lighttpd update con->dst_addr_buf to the actual remote address, leading to an IP address in REMOTE_ADDR for your CGI.
Updated by gstrauss about 7 years ago
--- a/src/inet_ntop_cache.c +++ b/src/inet_ntop_cache.c @@ -474,6 +474,9 @@ const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) { int i; UNUSED(srv); + #ifdef HAVE_SYS_UN_H + if (addr->plain.sa_family == AF_UNIX) return addr->un.sun_path; + #endif for (i = 0; i < INET_NTOP_CACHE_MAX; i++) { if (inet_ntop_cache[i].family == addr->plain.sa_family) { if (inet_ntop_cache[i].family == AF_INET6 && @@ -515,6 +518,9 @@ const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) { return inet_ntop_cache[i].b2; #else UNUSED(srv); + #ifdef HAVE_SYS_UN_H + if (addr->plain.sa_family == AF_UNIX) return addr->un.sun_path; + #endif return inet_ntoa(addr->ipv4.sin_addr); #endif }
Updated by davidm about 7 years ago
gstrauss wrote:
Do you think this is still an issue in lighttpd git master? CGI gets REMOTE_ADDR from con->dst_addr_buf, which will be "" for AF_UNIX with current behavior of inet_ntop_cache_get_ip().
That would work fine for our purposes. We just need a way to identify a request that was forwarded from our proxy.
Maybe sun_path should be returned for AF_UNIX (as you first suggested), since con->dst_addr_buf is used in many places, not just for the CGI environment.
I tried that but sun_path doesn't (usually) have a valid path so you get garbage there.
Regarding the language in RFC3875, if you are using lighttpd with AF_UNIX sockets, and you need a valid REMOTE_ADDR, you are probably proxying, and so you can use mod_extforward to have lighttpd update con->dst_addr_buf to the actual remote address, leading to an IP address in REMOTE_ADDR for your CGI.
In our case, we just need to know whether the request come from our proxy (running on the same machine) or directly via LAN/WAN. We don't care about the IP address of where the request originated.
Updated by gstrauss about 7 years ago
I tried that but sun_path doesn't (usually) have a valid path so you get garbage there.
What operating system? With the patch above, con->dst_addr_buf should contain the value obtained from the (sockaddr *) filled in by accept() or accept4() or paccept(), as long as you're testing with lighttpd git master.
Updated by gstrauss about 7 years ago
In our case, we just need to know whether the request come from our proxy (running on the same machine) or directly via LAN/WAN. We don't care about the IP address of where the request originated.
For this specific need, you can use mod_setenv to set an environment variable of your choosing within the $SERVER["socket"] condition in your lighttpd config.
Updated by davidm about 7 years ago
gstrauss wrote:
In our case, we just need to know whether the request come from our proxy (running on the same machine) or directly via LAN/WAN. We don't care about the IP address of where the request originated.
For this specific need, you can use mod_setenv to set an environment variable of your choosing within the $SERVER["socket"] condition in your lighttpd config.
Oh, I wasn't aware of that possibility. It seems to work great and is probably a more reliably solution as well. Thanks for the suggestion!
Updated by gstrauss about 7 years ago
- Status changed from New to Patch Pending
- Target version changed from 1.4.x to 1.4.46
Updated by gstrauss about 7 years ago
- Status changed from Patch Pending to Fixed
- % Done changed from 0 to 100
Applied in changeset 878dd9be499a7d271d808fdf73f804f9df77e564.
Also available in: Atom