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); }