-
Notifications
You must be signed in to change notification settings - Fork 106
Add user-defined headers before forward response to client #872
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple extensions are required.
etc/tempesta_fw.conf
Outdated
# | ||
# Default: | ||
# None. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't forget to add the description to the Wiki
tempesta_fw/vhost.c
Outdated
@@ -74,6 +75,8 @@ static size_t tfw_capolicy_sz = 0; /* Current size. */ | |||
*/ | |||
#define TFW_NIPDEF_ARRAY_SZ (64) | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary empty line
tempesta_fw/http.c
Outdated
@@ -1762,6 +1789,10 @@ tfw_http_adjust_resp(TfwHttpResp *resp, TfwHttpReq *req) | |||
if (r < 0) | |||
return r; | |||
|
|||
r = tfw_http_add_loc_hdrs(hm, req); | |||
if (r < 0) | |||
return r; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not only requests are must be adjustable - an example from the issue hdr_add Expires "Thu, 15 Apr 2020 20:00:00 GMT"
is about responses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually only responses are adjusted in the patch: tfw_http_add_loc_hdrs()
function is called in the tfw_http_adjust_resp()
as a part of response processing. Is it required to adjust requests before forwarding them to backend servers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, my bad - of course I was commenting tfw_http_adjust_resp()
:)
We absolutely have to be able to adjust requests before forwarding them to a backend. X-Forwarded-For
is the most trivial example which we hard code for now. Other examples could be security tokens passed to most powerful WAFs or removing some danger headers from suspicious requests.
tempesta_fw/http.c
Outdated
BUG_ON(!loc); | ||
|
||
for (i = 0; i < loc->usr_hdrs_sz; ++i) { | ||
r = tfw_http_msg_hdr_add(hm, loc->usr_hdrs[i]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the issue isn't clear: it's titled "transform custom HTTP headers", but specifies hdr_add
only. There is reference to Nginx's proxy_set_header
which adds a header in all cases except Host and Connection headers when it actually replaces them. That's absolutely non-flexible. It's better to allow a user to delete and replace any headers as well as add it, so please add header deletion and substitution as well:
hdr_del <header name>
hdr_sub <header name> <header value>
TFW_HTTP_HDR_USER_AGENT is equals to TFW_HTTP_HDR_SERVER
678a15e
to
57c364a
Compare
# TAG: req_hdr_set | ||
# | ||
# Replace or remove a user-defined header from HTTP request message before | ||
# forwarding it to backend server. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, make sense. But isn't it better to leave only one configuration option like req_hdr_xfrm
? E.g. to add or replace content of X-Forwarded-For
(as oposite to current hardcoded version it replaces the header if it's present in the request:
req_hdr_xfrm X-Forwarded-For 127.0.0.1
or to remove we just omit the value:
req_hdr_xfrm X-Forwarded-For
Just like tfw_http_msg_hdr_xfrm()
. The same for responses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only difference between req_hdr_add
and req_hdr_set
is ability of _add
to append user defined string to the existing header. In this case original value of header will be saved, but a user defined string will be added to the header. If the feature is not required, req_hdr_add
directive can be easily removed.
E.g. for the configuration resp_hdr_add Set-Cookie "ck=djnfsdnfkdn"
the header
Set-Cookie: c=fvfkm
will be transformed into Set-Cookie: c=fvfkm, ck=djnfsdnfkdn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So resp_hdr_set
deletes a header, adds it to a HTTP message or replaces a header if it's already present, is it correct? If so, then please describe the difference in https://github.com/tempesta-tech/tempesta/wiki/Modify-HTTP-Messages , preferably with some examples.
tempesta_fw/msg.h
Outdated
TFW_HTTP_MSG_RESP, | ||
|
||
TFW_HTTP_MSG_NUM | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are clearly HTTP constants, why aren't they in http_msg.h
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment is still not addressed.
@@ -79,7 +140,6 @@ __http_msg_hdr_val(TfwStr *hdr, unsigned id, TfwStr *val, bool client) | |||
[TFW_HTTP_HDR_X_FORWARDED_FOR] = SLEN("X-Forwarded-For:"), | |||
[TFW_HTTP_HDR_KEEP_ALIVE] = SLEN("Keep-Alive:"), | |||
[TFW_HTTP_HDR_TRANSFER_ENCODING] = SLEN("Transfer-Encoding:"), | |||
[TFW_HTTP_HDR_USER_AGENT] = SLEN("User-Agent:"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why User-Agent
is removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks confusing to init the same array member twice, since
Line 186 in 81b45c2
TFW_HTTP_HDR_SERVER = TFW_HTTP_HDR_USER_AGENT, |
The User-agent
case is checked in a few lines below:
tempesta/tempesta_fw/http_msg.c
Line 100 in 81b45c2
nlen = SLEN("User-Agent:"); |
tempesta_fw/http_msg.c
Outdated
@@ -26,6 +26,67 @@ | |||
#include "http_msg.h" | |||
#include "ss_skb.h" | |||
|
|||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update the copyright year in all the affected files.
tempesta_fw/http_msg.c
Outdated
#undef TfwStr_string | ||
}; | ||
DEFINE_TFW_STR(user_agent, "User-Agent:"); | ||
DEFINE_TFW_STR(if_none_match, "If-None-Match:"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the two headers aren't in the array? It's better to use bit different code for requests and responses. The function is used in tfw_cfgop_mod_hdr()
only and there you have msg_type
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this why I wrote "It's better to use bit different code for requests and responses. The function is used in tfw_cfgop_mod_hdr() only and there you have msg_type." It's can be figured out why the code looks exactly this, but from first glance it looks strange and it's better to rework it in more straightforward way.
tempesta_fw/http_msg.c
Outdated
if (!tfw_stricmpspn(hdr, &user_agent, ':')) | ||
return TFW_HTTP_HDR_USER_AGENT; | ||
if (!tfw_stricmpspn(hdr, &if_none_match, ':')) | ||
return TFW_HTTP_HDR_IF_NONE_MATCH; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, the function is used on configuration phase only. Please write this in a coment or use binary search in it since tfw_stricmpspn()
returns the strings relation - it's just confusing to see the linear scan.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually there is __tfw_http_msg_find_hdr()
function for binary search. But it requires alphabetically sorted array. That's not true for the array since original tfw_http_hdr_t
is not sorted. The function is called only at configuration processing, so i've decided to keep it as clean as possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, then just point out this in a comment.
My concern is that we have several library-like files (str.[ch], ss_skb.[ch], http_msg.[ch]) which contain logic useful in various situations. The function also looks like very useful in future, so it's necessary either to limit it's usage or write in in very solid way.
tempesta_fw/http_msg.c
Outdated
* Get header id in header table for header @hdr. | ||
*/ | ||
unsigned int | ||
tfw_http_msg_is_spec_hdr(const TfwStr *hdr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to rename the function to tfw_http_msg_spec_hid()
or tfw_http_msg_spec_hdr_id()
- it returns the ID and doesn't answer IS question.
} | ||
|
||
return dst; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a test for the function to t/unit/test_tfw_str.c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to merge with the couple cleanups.
tempesta_fw/msg.h
Outdated
TFW_HTTP_MSG_RESP, | ||
|
||
TFW_HTTP_MSG_NUM | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment is still not addressed.
tempesta_fw/http_msg.c
Outdated
unsigned int id; /* id in TfwHttpHdrTbl */ | ||
} TfwHdrDef; | ||
#define TfwStrHdr(v, id) {{ (v), NULL, sizeof(v) - 1, 0 }, (id) } | ||
static TfwHdrDef resp_hdrs[] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add const
type specification to allow the compiler do better optimization job.
tempesta_fw/http_msg.c
Outdated
/** | ||
* Get header id in header table for header @hdr. | ||
* | ||
* TODO: return error if header is not allowed in @msg_type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good topic to discuss and think about. Really, having Server
header in a request doesn't look normal. However, there are Web applications setting custom headers. Moreover, there are proprietary soft (e.g. AntiBViruses) actively working with their clouds using HTTP and the soft sometimes sends quite strange traffic.
Maybe this is a subject for machine learning (to learn the normal set of HTTP headers). Maybe we should provide a configuration option to allow a user to specify which headers are allowed, like we're going to do this for HTTP strings alphabets in #628.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function checks only headers added by end user. The (resp|req)_hdr_set
gives user opportunity to make very strange requests and responses and even broke network interactions between agents and server. But user must know what he does.
Maybe we should provide a configuration option to allow a user to specify which headers are allowed
It's already here: user can block specific headers in network by with (resp|req)_hdr_set <SomeHeader>
; all the headers will be removed from forwarded traffic.
tempesta_fw/http_msg.c
Outdated
|
||
return tfw_strdup(pool, &tmp_hdr); | ||
} | ||
EXPORT_SYMBOL(tfw_http_msg_make_hdr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no need to export the symbol. Please never export symbols in vain and for unit tests (I fixed several such exports)!
tempesta_fw/http_msg.c
Outdated
@@ -26,14 +26,39 @@ | |||
#include "http_msg.h" | |||
#include "ss_skb.h" | |||
|
|||
/** | |||
* Build TfwStr repesented HTTP header. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
repesented
-> represented
tempesta_fw/http_msg.c
Outdated
} | ||
|
||
/** | ||
* Get header id in requestf header table for header @hdr. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requestf
-> request
tempesta_fw/http_msg.c
Outdated
@@ -532,49 +613,37 @@ __hdr_sub(TfwHttpMsg *hm, char *name, size_t n_len, char *val, size_t v_len, | |||
|
|||
/** | |||
* Transform HTTP message @hm header with identifier @hid. | |||
* Raw header transforers must provide the header name by @name and @n_len. | |||
* If @val is NULL, then the header will be deleted from @hm. | |||
* @hdr must be compaund string and containt two or three parts: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
containt
-> contain
tempesta_fw/http_msg.c
Outdated
@@ -45,7 +70,7 @@ __tfw_http_msg_find_hdr(const TfwStr *hdr, const TfwStr array[], size_t size) | |||
|
|||
while (start < end) { | |||
size_t mid = start + (end - start) / 2; | |||
const TfwStr *sh = &array[mid]; | |||
const TfwStr *sh = (array + mid * member_sz); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that brackets are excess here.
tempesta_fw/http_msg.c
Outdated
|
||
return tfw_strdup(pool, &tmp_hdr); | ||
} | ||
|
||
/** | ||
* Find @hdr in @array. @array must be in lowercase and sorted in alphabetical |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the lowercase requirement still relevant for this function?
tempesta_fw/vhost.c
Outdated
* and current location. | ||
* | ||
* @req - http request to deturmine location; | ||
* @msg_type - Target message type (TFW_HTTP_MSG_REQ or TFW_HTTP_MSG_RESP). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arguments description doesn't seem to reflect current function signature.
tempesta_fw/vhost.c
Outdated
}; | ||
|
||
/* Pool for 'hdr_add' directive (TfwLocation->usr_hdrs) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like obsolete comment: TfwLocation->usr_hdrs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to merge with some minor corrections.
fix #511