The real-remote-addr function currently returns the value of the x-forwarded-for header if it's set, or remote-addr if it's not. In the case of chains of proxies, this gives unexpected results as each proxy appends the address it's proxying for onto the end of the list.
Since I imagine this function is intended to be used in situations where Hunchentoot is sitting behind proxies of its own, I've written a function to split things up to give a particular entry in this chain. Most of the time, I imagine you'd just want the address added by the closest proxy but if (for example) you're behind mod_proxy behind squid, this function can tell you the address of the agent that hit the squid server.
I'm not actually quite sure what to call this function. Originally at my local site I'd called it "real-remote-addr", replacing Hunchentoot's own function, but the name's not sitting easily with me. For one thing, it's got a different API since it takes the number of hops along the proxy chain to look, and for another it returns NIL if you fall off the end of the chain (I'm not quite sure that's correct, but it seems to me to fail better than DWIMly returning the last available address, since values supplied by the user's original request are useless anyway). Anyway, here it is, still with the name real-remote-addr.
(defvar *proxy-count* 0 "The length of the chain of server-side proxies in front of Hunchentoot.")
(defun real-remote-addr (&optional (nth *proxy-count*) (request *request*)) "Returns the address of the NTH host in the chain of proxies that set the X-Forwarded-For header. 0 is the address of the last proxy (or the client, if there are no proxies), 1 the address of the second proxy (or client if there is only one), and so forth." (if (zerop nth) (remote-addr request) (let* ((proxies (loop with xff = (header-in :x-forwarded-for request) for pos = 0 then (1+ comma) for comma = (position #, xff :start pos) collect (string-trim " " (subseq xff pos comma)) while comma)) (position (- (length proxies) nth))) (if (minusp position) nil (nth position proxies)))))