This can be useful in order to extend ACL and log format with upstream
proxy information when accept-proxy or accept-netscaler-cip is being
used
---
include/proto/connection.h | 32 ++++++++++++++++++++++++++++++++
include/types/connection.h | 9 ++++++++-
src/connection.c | 42 ++++++++++++++++++++++++++++++++++++++++++
src/session.c | 4 ++--
4 files changed, 84 insertions(+), 3 deletions(-)
diff --git a/include/proto/connection.h b/include/proto/connection.h
index ef078add2f20..86087950b421 100644
--- a/include/proto/connection.h
+++ b/include/proto/connection.h
@@ -524,6 +524,22 @@ static inline void conn_get_from_addr(struct connection
*conn)
conn->flags |= CO_FL_ADDR_FROM_SET;
}
+/* Retrieves the connection's proxy source address */
+static inline void conn_get_from_proxy_addr(struct connection *conn)
+{
+ if (conn->flags & CO_FL_PROXY_ADDR_FROM_SET)
+ return;
+
+ if (!conn_ctrl_ready(conn) || !conn->ctrl->get_src)
+ return;
+
+ if (conn->ctrl->get_src(conn->t.sock.fd, (struct sockaddr
*)&conn->proxy_addr.from,
+ sizeof(conn->proxy_addr.from),
+ obj_type(conn->target) != OBJ_TYPE_LISTENER) ==
-1)
+ return;
+ conn->flags |= CO_FL_PROXY_ADDR_FROM_SET;
+}
+
/* Retrieves the connection's original destination address */
static inline void conn_get_to_addr(struct connection *conn)
{
@@ -540,6 +556,22 @@ static inline void conn_get_to_addr(struct connection
*conn)
conn->flags |= CO_FL_ADDR_TO_SET;
}
+/* Retrieves the connection's proxy destination address */
+static inline void conn_get_to_proxy_addr(struct connection *conn)
+{
+ if (conn->flags & CO_FL_PROXY_ADDR_TO_SET)
+ return;
+
+ if (!conn_ctrl_ready(conn) || !conn->ctrl->get_dst)
+ return;
+
+ if (conn->ctrl->get_dst(conn->t.sock.fd, (struct sockaddr
*)&conn->proxy_addr.to,
+ sizeof(conn->proxy_addr.to),
+ obj_type(conn->target) != OBJ_TYPE_LISTENER) ==
-1)
+ return;
+ conn->flags |= CO_FL_PROXY_ADDR_TO_SET;
+}
+
/* Attaches a connection to an owner and assigns a data layer */
static inline void conn_attach(struct connection *conn, void *owner, const
struct data_cb *data)
{
diff --git a/include/types/connection.h b/include/types/connection.h
index beb9b898e2cd..0576778f62b1 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -126,7 +126,10 @@ enum {
/* This connection may not be shared between clients */
CO_FL_PRIVATE = 0x10000000,
- /* unused : 0x20000000, 0x40000000 */
+ /* These flags are used to report whether the from/to proxy
+ * addresses are set or not */
+ CO_FL_PROXY_ADDR_FROM_SET = 0x20000000, /* proxy_addr.from is set */
+ CO_FL_PROXY_ADDR_TO_SET = 0x40000000, /* proxy_addr.to is set */
/* This last flag indicates that the transport layer is used (for
instance
* by logs) and must not be cleared yet. The last call to
conn_xprt_close()
@@ -286,6 +289,10 @@ struct connection {
struct sockaddr_storage from; /* client address, or address
to spoof when connecting to the server */
struct sockaddr_storage to; /* address reached by the
client, or address to connect to */
} addr; /* addresses of the remote side, client for producer and server
for consumer */
+ struct {
+ struct sockaddr_storage from; /* upstream proxy address */
+ struct sockaddr_storage to; /* address reached by upstream
proxy */
+ } proxy_addr; /* Addresses of the upstream proxy if accept-proxy or
accept-netscaler-cip is used */
};
/* proxy protocol v2 definitions */
diff --git a/src/connection.c b/src/connection.c
index 7a9f3913ca74..380dca1b5370 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -420,6 +420,13 @@ int conn_recv_proxy(struct connection *conn, int flag)
if (*line++ != '\n')
goto bad_header;
+ /* update the session's proxy addresses and mark them set */
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.from, (struct
sockaddr_in *)&conn->addr.from,
+ sizeof(struct sockaddr_in));
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.to, (struct
sockaddr_in *)&conn->addr.to,
+ sizeof(struct sockaddr_in));
+ conn->flags |= CO_FL_PROXY_ADDR_TO_SET |
CO_FL_PROXY_ADDR_TO_SET;
+
/* update the session's addresses and mark them set */
((struct sockaddr_in *)&conn->addr.from)->sin_family =
AF_INET;
((struct sockaddr_in *)&conn->addr.from)->sin_addr.s_addr =
htonl(src3);
@@ -481,6 +488,13 @@ int conn_recv_proxy(struct connection *conn, int flag)
if (inet_pton(AF_INET6, dst_s, (void *)&dst3) != 1)
goto bad_header;
+ /* update the session's proxy addresses and mark them set */
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.from, (struct
sockaddr_in *)&conn->addr.from,
+ sizeof(struct sockaddr_in));
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.to, (struct
sockaddr_in *)&conn->addr.to,
+ sizeof(struct sockaddr_in));
+ conn->flags |= CO_FL_PROXY_ADDR_TO_SET |
CO_FL_PROXY_ADDR_TO_SET;
+
/* update the session's addresses and mark them set */
((struct sockaddr_in6 *)&conn->addr.from)->sin6_family =
AF_INET6;
memcpy(&((struct sockaddr_in6 *)&conn->addr.from)->sin6_addr,
&src3, sizeof(struct in6_addr));
@@ -527,6 +541,13 @@ int conn_recv_proxy(struct connection *conn, int flag)
if (ntohs(hdr_v2->len) < PP2_ADDR_LEN_INET)
goto bad_header;
+ /* update the session's proxy addresses and mark them
set */
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.from,
(struct sockaddr_in *)&conn->addr.from,
+ sizeof(struct sockaddr_in));
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.to,
(struct sockaddr_in *)&conn->addr.to,
+ sizeof(struct sockaddr_in));
+ conn->flags |= CO_FL_PROXY_ADDR_TO_SET |
CO_FL_PROXY_ADDR_TO_SET;
+
((struct sockaddr_in *)&conn->addr.from)->sin_family =
AF_INET;
((struct sockaddr_in
*)&conn->addr.from)->sin_addr.s_addr = hdr_v2->addr.ip4.src_addr;
((struct sockaddr_in *)&conn->addr.from)->sin_port =
hdr_v2->addr.ip4.src_port;
@@ -541,6 +562,13 @@ int conn_recv_proxy(struct connection *conn, int flag)
if (ntohs(hdr_v2->len) < PP2_ADDR_LEN_INET6)
goto bad_header;
+ /* update the session's proxy addresses and mark them
set */
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.from,
(struct sockaddr_in *)&conn->addr.from,
+ sizeof(struct sockaddr_in));
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.to,
(struct sockaddr_in *)&conn->addr.to,
+ sizeof(struct sockaddr_in));
+ conn->flags |= CO_FL_PROXY_ADDR_TO_SET |
CO_FL_PROXY_ADDR_TO_SET;
+
((struct sockaddr_in6 *)&conn->addr.from)->sin6_family
= AF_INET6;
memcpy(&((struct sockaddr_in6
*)&conn->addr.from)->sin6_addr, hdr_v2->addr.ip6.src_addr, 16);
((struct sockaddr_in6 *)&conn->addr.from)->sin6_port =
hdr_v2->addr.ip6.src_port;
@@ -733,6 +761,13 @@ int conn_recv_netscaler_cip(struct connection *conn, int
flag)
hdr_tcp = (struct my_tcphdr *)(line + (hdr_ip4->ip_hl * 4));
+ /* update the session's proxy addresses and mark them set */
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.from, (struct
sockaddr_in *)&conn->addr.from,
+ sizeof(struct sockaddr_in));
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.to, (struct
sockaddr_in *)&conn->addr.to,
+ sizeof(struct sockaddr_in));
+ conn->flags |= CO_FL_PROXY_ADDR_TO_SET |
CO_FL_PROXY_ADDR_TO_SET;
+
/* update the session's addresses and mark them set */
((struct sockaddr_in *)&conn->addr.from)->sin_family = AF_INET;
((struct sockaddr_in *)&conn->addr.from)->sin_addr.s_addr =
hdr_ip4->ip_src.s_addr;
@@ -766,6 +801,13 @@ int conn_recv_netscaler_cip(struct connection *conn, int
flag)
hdr_tcp = (struct my_tcphdr *)(line + sizeof(struct ip6_hdr));
+ /* update the session's proxy addresses and mark them set */
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.from, (struct
sockaddr_in *)&conn->addr.from,
+ sizeof(struct sockaddr_in));
+ memcpy ((struct sockaddr_in *)&conn->proxy_addr.to, (struct
sockaddr_in *)&conn->addr.to,
+ sizeof(struct sockaddr_in));
+ conn->flags |= CO_FL_PROXY_ADDR_TO_SET |
CO_FL_PROXY_ADDR_TO_SET;
+
/* update the session's addresses and mark them set */
((struct sockaddr_in6 *)&conn->addr.from)->sin6_family =
AF_INET6;
((struct sockaddr_in6 *)&conn->addr.from)->sin6_addr =
hdr_ip6->ip6_src;
diff --git a/src/session.c b/src/session.c
index cdf57e388a26..90a465c1fb31 100644
--- a/src/session.c
+++ b/src/session.c
@@ -138,13 +138,13 @@ int session_accept_fd(struct listener *l, int cfd, struct
sockaddr_storage *addr
/* wait for a PROXY protocol header */
if (l->options & LI_O_ACC_PROXY) {
- cli_conn->flags |= CO_FL_ACCEPT_PROXY;
+ cli_conn->flags |= CO_FL_PROXY_ADDR_FROM_SET |
CO_FL_ACCEPT_PROXY;
conn_sock_want_recv(cli_conn);
}
/* wait for a NetScaler client IP insertion protocol header */
if (l->options & LI_O_ACC_CIP) {
- cli_conn->flags |= CO_FL_ACCEPT_CIP;
+ cli_conn->flags |= CO_FL_PROXY_ADDR_FROM_SET | CO_FL_ACCEPT_CIP;
conn_sock_want_recv(cli_conn);
}