Skip to content

Commit 0ae4c3e

Browse files
committed
use ip from x-forwarded-for for searching a client
1 parent de48af3 commit 0ae4c3e

File tree

7 files changed

+47
-18
lines changed

7 files changed

+47
-18
lines changed

tempesta_fw/client.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ addr_eq(TdbRec *rec, void *data)
7878
}
7979

8080
/**
81-
* Find a client corresponding to the @sk by IP address.
81+
* Find a client corresponding to @addr.
8282
* More advanced identification is possible based on User-Agent,
8383
* Cookie and other HTTP headers.
8484
* TODO (#488,#598,#1054?) actually clients can be relatively reliably
@@ -88,19 +88,17 @@ addr_eq(TdbRec *rec, void *data)
8888
* when the @sk is closed.
8989
*/
9090
TfwClient *
91-
tfw_client_obtain(struct sock *sk, void (*init)(TfwClient *))
91+
tfw_client_obtain(TfwAddr addr, void (*init)(TfwClient *))
9292
{
9393
TfwClientEntry *ent;
9494
TfwClient *cli;
9595
unsigned long key;
96-
TfwAddr addr;
9796
size_t len;
9897
TdbRec *rec;
9998
bool is_new;
10099
int conn_users;
101100
time_t curr_time = tfw_current_timestamp();
102101

103-
ss_getpeername(sk, &addr);
104102
key = hash_calc((const char *)&addr.sin6_addr,
105103
sizeof(addr.sin6_addr));
106104

tempesta_fw/client.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ typedef struct {
4040
TfwClassifierPrvt class_prvt;
4141
} TfwClient;
4242

43-
TfwClient *tfw_client_obtain(struct sock *sk, void (*init)(TfwClient *));
43+
TfwClient *tfw_client_obtain(TfwAddr addr, void (*init)(TfwClient *));
4444
void tfw_client_put(TfwClient *cli);
4545
int tfw_client_for_each(int (*fn)(void *));
4646
void tfw_cli_conn_release(TfwCliConn *cli_conn);

tempesta_fw/connection.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ tfw_connection_init(TfwConn *conn)
4141
void
4242
tfw_connection_link_peer(TfwConn *conn, TfwPeer *peer)
4343
{
44-
BUG_ON(conn->peer || !list_empty(&conn->list));
44+
BUG_ON(!list_empty(&conn->list));
4545
conn->peer = peer;
4646
tfw_peer_add_conn(peer, &conn->list);
4747
}

tempesta_fw/http.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2828,6 +2828,9 @@ tfw_http_req_process(TfwConn *conn, const TfwFsmData *data)
28282828
TfwHttpMsg *hmsib;
28292829
TfwHttpParser *parser;
28302830
TfwFsmData data_up;
2831+
TfwAddr addr;
2832+
TfwStr s_xff, s_ip, *c, *end;
2833+
unsigned int nchunks;
28312834

28322835
BUG_ON(!conn->msg);
28332836
BUG_ON(off >= skb->len);
@@ -2931,6 +2934,30 @@ tfw_http_req_process(TfwConn *conn, const TfwFsmData *data)
29312934
skb = NULL;
29322935
}
29332936

2937+
/*
2938+
* If a client work through a forward proxy, then a proxy can pass it's
2939+
* IP address by the first value in X-Forwarded-For
2940+
*/
2941+
s_xff = req->h_tbl->tbl[TFW_HTTP_HDR_X_FORWARDED_FOR];
2942+
s_ip = tfw_str_next_str_val(&s_xff);
2943+
nchunks = 0;
2944+
TFW_STR_FOR_EACH_CHUNK(c, &s_ip, end) {
2945+
if (!(c->flags & TFW_STR_VALUE))
2946+
break;
2947+
nchunks++;
2948+
}
2949+
s_ip.nchunks = nchunks;
2950+
2951+
if (!TFW_STR_EMPTY(&s_ip) && tfw_addr_pton(&s_ip, &addr) == 0) {
2952+
TfwClient *cli = tfw_client_obtain(addr, NULL);
2953+
TfwClient *conn_cli = (TfwClient *)conn->peer;
2954+
if (cli && conn_cli != cli) {
2955+
tfw_connection_unlink_from_peer(conn);
2956+
tfw_client_put(conn_cli);
2957+
tfw_connection_link_peer(conn, (TfwPeer *)cli);
2958+
}
2959+
}
2960+
29342961
/*
29352962
* Sticky cookie module must be used before request can reach cache.
29362963
* Unauthorised clients mustn't be able to get any resource on

tempesta_fw/http_limits.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,10 @@ frang_conn_new(struct sock *sk)
335335
FrangAcc *ra;
336336
TfwClient *cli;
337337
FrangCfg *conf = tfw_vhost_global_frang_cfg();
338+
TfwAddr addr;
338339

339-
cli = tfw_client_obtain(sk, __frang_init_acc);
340+
ss_getpeername(sk, &addr);
341+
cli = tfw_client_obtain(addr, __frang_init_acc);
340342
if (unlikely(!cli)) {
341343
TFW_ERR("can't obtain a client for frang accounting\n");
342344
return TFW_BLOCK;

tempesta_fw/http_parser.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3223,27 +3223,27 @@ __req_parse_x_forwarded_for(TfwHttpMsg *hm, unsigned char *data, size_t len)
32233223
__FSM_STATE(Req_I_XFF) {
32243224
/* Eat OWS before the node ID. */
32253225
if (unlikely(IS_WS(c)))
3226-
__FSM_I_MOVE(Req_I_XFF);
3226+
__FSM_I_MOVE_fixup(Req_I_XFF, 1, 0);
32273227
/*
32283228
* Eat IP address or host name.
32293229
*
32303230
* TODO: parse/validate IP addresses and textual IDs.
32313231
* Currently we just validate separate characters, but the
32323232
* whole value may be invalid (e.g. "---[_..[[").
32333233
*/
3234-
__FSM_I_MATCH_MOVE(xff, Req_I_XFF_Node_Id);
3234+
__FSM_I_MATCH_MOVE_fixup(xff, Req_I_XFF_Node_Id, TFW_STR_VALUE);
32353235
if (unlikely(!__fsm_sz))
32363236
return CSTR_NEQ;
3237-
__FSM_I_MOVE_n(Req_I_XFF_Sep, __fsm_sz);
3237+
__FSM_I_MOVE_fixup(Req_I_XFF_Sep, __fsm_sz, TFW_STR_VALUE);
32383238
}
32393239

32403240
/*
32413241
* At this state we know that we saw at least one character as
32423242
* a host address and now we can pass zero length token.
32433243
*/
32443244
__FSM_STATE(Req_I_XFF_Node_Id) {
3245-
__FSM_I_MATCH_MOVE(xff, Req_I_XFF_Node_Id);
3246-
__FSM_I_MOVE_n(Req_I_XFF_Sep, __fsm_sz);
3245+
__FSM_I_MATCH_MOVE_fixup(xff, Req_I_XFF_Node_Id, TFW_STR_VALUE);
3246+
__FSM_I_MOVE_fixup(Req_I_XFF_Sep, __fsm_sz, TFW_STR_VALUE);
32473247
}
32483248

32493249
__FSM_STATE(Req_I_XFF_Sep) {
@@ -3256,14 +3256,14 @@ __req_parse_x_forwarded_for(TfwHttpMsg *hm, unsigned char *data, size_t len)
32563256

32573257
/* OWS before comma or before EOL (is unusual). */
32583258
if (unlikely(IS_WS(c)))
3259-
__FSM_I_MOVE(Req_I_XFF_Sep);
3259+
__FSM_I_MOVE_fixup(Req_I_XFF_Sep, 1, 0);
32603260

32613261
/*
32623262
* Multiple subsequent commas look suspicious, so we don't
32633263
* stay in this state after the first comma is met.
32643264
*/
32653265
if (likely(c == ','))
3266-
__FSM_I_MOVE(Req_I_XFF);
3266+
__FSM_I_MOVE_fixup(Req_I_XFF, 1, 0);
32673267

32683268
return CSTR_NEQ;
32693269
}
@@ -4075,9 +4075,9 @@ tfw_http_parse_req(void *req_data, unsigned char *data, size_t len,
40754075
TFW_HTTP_HDR_TRANSFER_ENCODING);
40764076

40774077
/* 'X-Forwarded-For:*OWS' is read, process field-value. */
4078-
TFW_HTTP_PARSE_SPECHDR_VAL(Req_HdrX_Forwarded_ForV, Req_I_XFF,
4079-
msg, __req_parse_x_forwarded_for,
4080-
TFW_HTTP_HDR_X_FORWARDED_FOR);
4078+
__TFW_HTTP_PARSE_SPECHDR_VAL(Req_HdrX_Forwarded_ForV, Req_I_XFF,
4079+
msg, __req_parse_x_forwarded_for,
4080+
TFW_HTTP_HDR_X_FORWARDED_FOR, 0);
40814081

40824082
/* 'User-Agent:*OWS' is read, process field-value. */
40834083
TFW_HTTP_PARSE_SPECHDR_VAL(Req_HdrUser_AgentV, Req_I_UserAgent,

tempesta_fw/sock_clnt.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ tfw_sock_clnt_new(struct sock *sk)
145145
TfwClient *cli;
146146
TfwConn *conn;
147147
SsProto *listen_sock_proto;
148+
TfwAddr addr;
148149

149150
TFW_DBG3("new client socket: sk=%p, state=%u\n", sk, sk->sk_state);
150151
TFW_INC_STAT_BH(clnt.conn_attempts);
@@ -158,7 +159,8 @@ tfw_sock_clnt_new(struct sock *sk)
158159
listen_sock_proto = sk->sk_user_data;
159160
tfw_connection_unlink_from_sk(sk);
160161

161-
cli = tfw_client_obtain(sk, NULL);
162+
ss_getpeername(sk, &addr);
163+
cli = tfw_client_obtain(addr, NULL);
162164
if (!cli) {
163165
TFW_ERR("can't obtain a client for the new socket\n");
164166
return -ENOENT;

0 commit comments

Comments
 (0)