Added ACL for checking client's connection marks#106
Added ACL for checking client's connection marks#106k0rv1n wants to merge 1 commit intosquid-cache:masterfrom
Conversation
|
Can one of the admins verify this patch? |
rousskov
left a comment
There was a problem hiding this comment.
Thank you for improving Squid!
I see several problems in the patch, but connection marking is not my area of the expertise, so I hope that somebody else reviews it instead (and works with you to fix those problems).
Meanwhile, could you please clarify the relationship between your ACL and clientside_mark directive? Your ACL reads the markings set by client when talking to Squid, right? If clientside_mark is in effect, will it overwrite those client-set markings or do both set of markings co-exist in that case? Your explanation will affect some of the required fixes.
|
OK to test |
|
client_connmark ACL and clientside_mark directive are not interchangable. New ACL aims to check connection mark that is set by iptables, just like it's done for source or destination addresses, but it does not change a mark. |
|
I interpret your answer as
Please correct me if my understanding is wrong. |
| ACLConnMark::parse() | ||
| { | ||
| while (char *t = ConfigParser::strtokFile()) { | ||
| std::string token(t); |
There was a problem hiding this comment.
Please use SBuf and Parser::Tokenizer for this parsing instead of std::string. That should remove the need for the above strToInt() custom implementation and allow detection of invalid data in or after the mask value.
Also the indentation should be 8 spaces, not tabs.
| } | ||
|
|
||
| if ((_mark == 0 && _mask == 0xffffffff) || (_mask == 0)) { | ||
| debugs(28, DBG_CRITICAL, "aclParseConnMark: bad mark '" << t << "'"); |
There was a problem hiding this comment.
Please use 'MYNAME << ": ' instead of '"aclParseConnMark: '.
same for the other critical level debugs
| uint32_t conn_mark = checklist->conn()->getClientConnection()->client_nfmark; | ||
|
|
||
| if (marks.empty()) { | ||
| return 1; |
There was a problem hiding this comment.
surely this should be impossible code since the parse() method is terminating Squid with self_destruct() when there are no marks configured.
If it can happen at all, then -1 (unable to match) seems a more appropriate result than successful match.
| continue; | ||
| } | ||
| uint32_t _mask = 0xffffffff; | ||
| uint32_t _mark = 0; |
There was a problem hiding this comment.
indentation is a little bit screwed up around these lines. probably because some are tabs and some are uneven number of spaces. Squid coding style uses 4 spaces for each level of indent.
Also, please use nfmark_t for Netfilter CONNMARK's.
| #define SQUID_ACLCONNMARK_H | ||
|
|
||
| #include "acl/Acl.h" | ||
| #include "map" |
There was a problem hiding this comment.
Map is a STL include not a local Squid one. Use angle brackets instead of quotes here.
| AclSizeLimit.cc \ | ||
| AclSizeLimit.h | ||
| AclSizeLimit.h \ | ||
| ConnMark.h \ |
There was a problem hiding this comment.
Please move these additions up to the C section below ConnectionsEncryptted.* entries. It also goes .cc before .h in the listing.
|
|
||
| bool handleRequestBodyData(); | ||
| // called to get client connmark | ||
| const Comm::ConnectionPointer getClientConnection(); |
There was a problem hiding this comment.
clientConnection is a public member from ::Server. No need to extend the ConnStateData API.
| #endif | ||
| } | ||
|
|
||
| nfmark_t Ip::Qos::getNfmarkFromClient(const Comm::ConnectionPointer &client) |
There was a problem hiding this comment.
Most of this new code is exact duplicate of the getNfmarkFromServer() method. It would be better to make that existing method a more generic getNfMakeFromConnection(...) and have getNfmarkFromServer() and getNfmarkFromClient() specialize from that by sending the appropriate callback pointer to the generic shared method.
Once done the "nfmark" member of Comm::ConnectionPointer should be the remote endpoints CONNMARK, regardless of whether it is a server or client connection. So you can remove the new client_connmark member.
The debugs currently at line 121 (and new line 171), when in the generic method can be made to print the Comm::ConnectionPointer to self-document the connection instead of mentioning destination and source explicitly.
Please also take the opportunity to convert debugs about strerror(errno) to xstrerr(xerrno) construct on new and changed code lines. The debugs() macro uses time lookup syscalls which can change errno contents - so it must be preserved explicitly. See line 74-75 in this file for how to do it properly.
| struct nf_conntrack *ct, | ||
| void *client_connmark) | ||
| { | ||
| nfmark_t *mark = (nfmark_t *)client_connmark; |
There was a problem hiding this comment.
Please use appropriate C++ casting (static_cast here) in new and updated code instead of C casts.
| cap_list[ncaps] = CAP_NET_BIND_SERVICE; | ||
| ++ncaps; | ||
| if (Ip::Interceptor.TransparentActive() || | ||
| Ip::Interceptor.InterceptActive() || |
There was a problem hiding this comment.
Why? the existing Netfilter operations apparently do not need this level of privileges, so there should be no reason to add them now.
There was a problem hiding this comment.
Without this capability netfilter says 'operation not permitted' when trying to get a connection mark. This makes sense, because we try to get a mark of a connection that is not created by squid. We query details of intercepted connection (that we do not own), so appropriate capability is a must here.
There was a problem hiding this comment.
I think you have found a Linux bug then. It should not require root level privileges for reading socket state with getsockopt(), only for changing the state with setsockopt(). Please add a TODO about looking into better restrictions later.
|
@rousskov, I'll try to clarify the idea of this (@k0rv1n and I are colleagues). Actually, this was designed for intercepted connections, not for explicit proxy configurations. For instance:
We've not checked if clientside_mark directive interferes with this new ACL, this case should be studied. Also, probably the name of the new ACL is a bit confusing and something like 'origin_nfmark' will be a better option. |
I am trying to understand what that statement means for Squid admins: Does the new ACL work for explicitly proxied connections? You may ignore clientside_mark directive interference when answering this question (it is important but a separate issue) -- assume no clientside_mark directive is in use.
The right name will depend, in part, on the new ACL interaction with clientside_mark and on whether the new ACL works as expected for explicitly proxied connections. Both are currently open issues. |
|
@yadij, nice review! You have spotted most of the problems I have seen and a couple I have missed. The few remaining ones may disappear while addressing the already reported problems. |
|
Thanks for great rewiev. I'll continue work with code on Monday. |
Sometimes it could be useful to check client's connection mark with ACL.