Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP/2 vs HTTPS handling #1643

Merged
merged 26 commits into from
Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
509e31c
Convert errors handling in tfw_sock_clnt_init() to more traditional way
krizhanovsky Jun 19, 2022
1958733
Store TFW_FSM_H2 in SsProto->type to separate HTTP/2 listening and
krizhanovsky Jun 20, 2022
0db6afb
Fix typos for the previous commit (TO BE SQUASHED)
krizhanovsky Jun 26, 2022
71ebe12
Use separate memory caches for HTTPS and H2 connections.
krizhanovsky Jul 6, 2022
c89698d
Don't try to clear H2 context on HTTPS connections.
krizhanovsky Jul 7, 2022
0e6efe3
Refactoring:
krizhanovsky Jul 14, 2022
8c4259f
Fix crash on an empty account descriptor for HTTP limiting: add a
krizhanovsky Jul 14, 2022
b95c9f2
Refactoring: there is no need to pass global tfw_mods as a parameter
krizhanovsky Aug 9, 2022
3bb0f5f
tfw_mods_stop() calls tfw_sock_clnt_stop() releasing all client sockets
krizhanovsky Aug 10, 2022
204861f
We don't use autovectorization any more, so the connection code doesn't
krizhanovsky Aug 10, 2022
27d5aed
Remove 'Bad TLS alert' message since it's raised on a peer
krizhanovsky Aug 13, 2022
7d8b8aa
Ignore ctags, csope and vim files
krizhanovsky Aug 13, 2022
136402f
Typically we call tfw_sock_clnt_drop() for TLS connections, when
krizhanovsky Aug 16, 2022
614a494
tfw_http_search_cookie() may pass chunk == end, which is past the last
krizhanovsky Aug 16, 2022
f492a0b
Fix KASAN use-after-free in tfw_connection_drop(): conn_drop hook
krizhanovsky Aug 17, 2022
617eb70
Add WS and WSS protocols for connection cache selector tfw_cli_cache() -
krizhanovsky Aug 17, 2022
9139078
Fix sockets hang after error during starting tempesta
const-t Aug 31, 2022
3d8037c
tfw_listen_sock_del_all: Fixed incorrect usage of list_for_each_entry
const-t Sep 1, 2022
06b2157
Update the code of ss_do_close() according to the current 5.10.35 code.
krizhanovsky Sep 2, 2022
3a82e94
Remove extra assertion (merged in other PR)
krizhanovsky Sep 2, 2022
eaabf8e
Fix memory leak in tfw_tls_conn_init() on unsuccessful call of
krizhanovsky Sep 2, 2022
f0fa97a
Better comment for tfw_peer_for_each_conn() about server and client
krizhanovsky Sep 2, 2022
2f3a6a3
Fix a typo and unnecessary nullification
krizhanovsky Sep 2, 2022
e8cfb48
Fix the race between tfw_sock_clnt_new() callback and
krizhanovsky Sep 4, 2022
4cfda82
Multiple fixes:
krizhanovsky Sep 4, 2022
96ba4f5
Fix small typos and a cleanup
krizhanovsky Sep 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ Module.symvers
*~
\#*\#
.\#*
*.orig
.*.swp

# ctags and cscope
cscope.*
tags

# eclipse project settings
.pydevproject
Expand Down
4 changes: 2 additions & 2 deletions fw/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Tempesta FW
*
* Copyright (C) 2014 NatSys Lab. (info@natsys-lab.com).
* Copyright (C) 2015-2018 Tempesta Technologies, Inc.
* Copyright (C) 2015-2022 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -43,7 +43,7 @@ int tfw_client_for_each(int (*fn)(void *));
void tfw_client_set_expires_time(unsigned int expires_time);
void tfw_cli_conn_release(TfwCliConn *cli_conn);
int tfw_cli_conn_send(TfwCliConn *cli_conn, TfwMsg *msg);
int tfw_cli_conn_close_all_sync(TfwClient *cli);
void tfw_cli_abort_all(void);

void tfw_tls_connection_lost(TfwConn *conn);

Expand Down
20 changes: 6 additions & 14 deletions fw/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,20 +69,13 @@ tfw_connection_repair(TfwConn *conn)
int
tfw_connection_close(TfwConn *conn, bool sync)
{
int r;

/*
* This function might be called from process context on Tempesta FW
* start or stop operation or from softirq, so need to save FPU context
* to call autovectorized synchronous sockets code.
*/
kernel_fpu_begin_mask(KFPU_MXCSR);

r = TFW_CONN_HOOK_CALL(conn, conn_close, sync);

kernel_fpu_end();
return TFW_CONN_HOOK_CALL(conn, conn_close, sync);
}

return r;
void
tfw_connection_abort(TfwConn *conn)
{
TFW_CONN_HOOK_CALL(conn, conn_abort);
}

/**
Expand All @@ -93,7 +86,6 @@ tfw_connection_drop(TfwConn *conn)
{
/* Ask higher levels to free resources at connection close. */
TFW_CONN_HOOK_CALL(conn, conn_drop);
BUG_ON(conn->stream.msg);
}

/*
Expand Down
44 changes: 39 additions & 5 deletions fw/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ enum {
Conn_HttpsClnt = Conn_Clnt | TFW_FSM_HTTPS,
Conn_HttpsSrv = Conn_Srv | TFW_FSM_HTTPS,

/* HTTP/2 */
Conn_H2Clnt = Conn_Clnt | TFW_FSM_H2,
Conn_H2Srv = Conn_Srv | TFW_FSM_H2,

/* Websocket plain */
Conn_WsClnt = Conn_HttpClnt | TFW_FSM_WEBSOCKET,
Conn_WsSrv = Conn_HttpSrv | TFW_FSM_WEBSOCKET,
Expand Down Expand Up @@ -235,11 +239,6 @@ typedef struct {

#define tfw_h2_context(conn) ((TfwH2Ctx *)(&((TfwH2Conn *)conn)->h2))

#define TFW_CONN_H2(c) \
(TFW_CONN_TLS((TfwConn *)c) \
&& tfw_tls_context(c)->alpn_chosen \
&& tfw_tls_context(c)->alpn_chosen->id == TTLS_ALPN_ID_HTTP2)

/* Callbacks used by l5-l7 protocols to operate on connection level. */
typedef struct {
/*
Expand All @@ -263,6 +262,13 @@ typedef struct {
*/
int (*conn_close)(TfwConn *conn, bool sync);

/*
* Called to abort a connection intentionally on Tempesta side.
* This is rough connection closing without any notifications like TLS
* alerts, probably with TCP RST or just silent connection termination.
*/
void (*conn_abort)(TfwConn *conn);

/*
* Called when closing a connection (client or server,
* as in conn_init()). This is required for modules that
Expand Down Expand Up @@ -518,6 +524,33 @@ tfw_connection_validate_cleanup(TfwConn *conn)
BUG_ON(rc && rc != TFW_CONN_DEATHCNT);
}

static inline int
tfw_peer_for_each_conn(TfwPeer *p, int (*cb)(TfwConn *))
{
int r = 0;
TfwConn *conn, *tmp_conn;

spin_lock_bh(&p->conn_lock);

/*
* @cb() may delete connections from the list.
* Typically, this happens on connection_drop callbacks on sockets closing.
* However, note that client and server connections drops are logically
* different: client connections are just freed with all linked resources,
* while the high level server connection handlers are preserved for
* connection repair and freed on shutdown only.
*/
list_for_each_entry_safe(conn, tmp_conn, &p->conn_list, list) {
r = cb(conn);
krizhanovsky marked this conversation as resolved.
Show resolved Hide resolved
if (unlikely(r))
break;
}

spin_unlock_bh(&(p)->conn_lock);

return r;
}

void tfw_connection_hooks_register(TfwConnHooks *hooks, int type);
void tfw_connection_hooks_unregister(int type);
int tfw_connection_send(TfwConn *conn, TfwMsg *msg);
Expand All @@ -530,6 +563,7 @@ void tfw_connection_link_peer(TfwConn *conn, TfwPeer *peer);
int tfw_connection_new(TfwConn *conn);
void tfw_connection_repair(TfwConn *conn);
int tfw_connection_close(TfwConn *conn, bool sync);
void tfw_connection_abort(TfwConn *conn);
void tfw_connection_drop(TfwConn *conn);
void tfw_connection_release(TfwConn *conn);

Expand Down
24 changes: 2 additions & 22 deletions fw/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ static unsigned int
tfw_ipv4_nf_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
int r;
const struct iphdr *ih;
struct in6_addr addr6;

Expand All @@ -161,16 +160,7 @@ tfw_ipv4_nf_hook(void *priv, struct sk_buff *skb,
if (tfw_filter_check_ip(&addr6) == TFW_BLOCK)
return NF_DROP;

/* Check classifiers for Layer 3. */
r = tfw_classify_ipv4(skb);
switch (r) {
case TFW_PASS:
return NF_ACCEPT;
case TFW_POSTPONE:
return NF_STOLEN;
}

return NF_DROP;
return NF_ACCEPT;
}

static u8 *
Expand Down Expand Up @@ -233,7 +223,6 @@ static unsigned int
tfw_ipv6_nf_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
int r;
struct ipv6hdr *ih;

ih = __ipv6_hdr_check(skb);
Expand All @@ -243,16 +232,7 @@ tfw_ipv6_nf_hook(void *priv, struct sk_buff *skb,
if (tfw_filter_check_ip(&ih->saddr) == TFW_BLOCK)
return NF_DROP;

/* Check classifiers for Layer 3. */
r = tfw_classify_ipv6(skb);
switch (r) {
case TFW_PASS:
return NF_ACCEPT;
case TFW_POSTPONE:
return NF_STOLEN;
}

return NF_DROP;
return NF_ACCEPT;
}

static struct nf_hook_ops tfw_nf_ops[] __read_mostly = {
Expand Down
18 changes: 15 additions & 3 deletions fw/gfsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,25 @@
* build real stack. This simplifies the protocols handling, makes it faster
* and provides more flexibility to set classification FSMs' hooks for
* specific secured application protocol.
*
* The constants are used in the less significant byte for connection or socket
* type, see also enums in connection.h and sync_socket.h.
*
* TODO #77: probably we should get rid of the FRANG states, call the http
* limiting callbacks directly and make the enum purely for the protocol
* type. Then the enum in connection.h determines server/client connection
* and from sync_socket.h the state of the connection. Now this enum looks
* inconsistent.
*/
enum {
/* Protocols */
TFW_FSM_HTTP,
TFW_FSM_HTTPS,
TFW_FSM_HTTP = 0,
TFW_FSM_HTTPS = 1,
/* h2c isn't supported, so HTTP/2 is always HTTPS */
TFW_FSM_H2 = 2 | TFW_FSM_HTTPS,

/* Not really a FSM, used for connection hook registration only */
TFW_FSM_WEBSOCKET,
TFW_FSM_WEBSOCKET = 4,
TFW_FSM_WS = TFW_FSM_WEBSOCKET | TFW_FSM_HTTP,
TFW_FSM_WSS = TFW_FSM_WEBSOCKET | TFW_FSM_HTTPS,

Expand Down
5 changes: 2 additions & 3 deletions fw/hpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,6 @@ do { \
WARN_ON_ONCE(hp->length); \
} while (0)

static unsigned long act_hp_str_n;

void
write_int(unsigned long index, unsigned short max, unsigned short mask,
TfwHPackInt *__restrict res_idx)
Expand Down Expand Up @@ -1093,8 +1091,10 @@ tfw_hpack_init(TfwHPack *__restrict hp, unsigned int htbl_sz)

err_et:
tfw_pool_destroy(dt->h_pool);
dt->h_pool = NULL;
err_dt:
tfw_pool_destroy(dt->pool);
dt->pool = NULL;

return -ENOMEM;
}
Expand All @@ -1105,7 +1105,6 @@ tfw_hpack_clean(TfwHPack *__restrict hp)
tfw_pool_destroy(hp->enc_tbl.pool);
tfw_pool_destroy(hp->dec_tbl.h_pool);
tfw_pool_destroy(hp->dec_tbl.pool);
WARN_ON_ONCE(act_hp_str_n);
}

/*
Expand Down
16 changes: 9 additions & 7 deletions fw/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -2538,7 +2538,7 @@ tfw_http_conn_msg_alloc(TfwConn *conn, TfwStream *stream)
else
tfw_http_init_parser_resp((TfwHttpResp *)hm);

if (TFW_CONN_H2(conn)) {
if (TFW_FSM_TYPE(conn->proto.type) == TFW_FSM_H2) {
TfwHttpReq *req = (TfwHttpReq *)hm;

if(!(req->pit.pool = __tfw_pool_new(0)))
Expand Down Expand Up @@ -2739,7 +2739,7 @@ static void tfw_http_resp_terminate(TfwHttpMsg *hm);
static void
tfw_http_conn_drop(TfwConn *conn)
{
bool h2_mode = TFW_CONN_H2(conn);
bool h2_mode = TFW_FSM_TYPE(conn->proto.type) == TFW_FSM_H2;

T_DBG2("%s: conn=[%p]\n", __func__, conn);

Expand Down Expand Up @@ -6545,14 +6545,16 @@ tfw_http_msg_process_generic(TfwConn *conn, TfwStream *stream,
int
tfw_http_msg_process(TfwConn *conn, struct sk_buff *skb)
{
int r;
TfwStream *stream = &((TfwConn *)conn)->stream;

r = TFW_CONN_H2(conn)
? tfw_h2_frame_process(conn, skb)
: tfw_http_msg_process_generic(conn, stream, skb);
WARN_ON_ONCE(TFW_CONN_TLS(conn) && tfw_tls_context(conn)->alpn_chosen
&& tfw_tls_context(conn)->alpn_chosen->id
== TTLS_ALPN_ID_HTTP2
&& TFW_FSM_TYPE(conn->proto.type) != TFW_FSM_H2);

return r;
if (TFW_FSM_TYPE(conn->proto.type) == TFW_FSM_H2)
return tfw_h2_frame_process(conn, skb);
return tfw_http_msg_process_generic(conn, stream, skb);
}

/**
Expand Down
Loading