Re: tproxy using conntrack/nat?
On Thu, May 23, 2002 at 12:56:58PM +0200, Balazs Scheidler wrote: I see two possibilities: * add a new argument to ip_nat_setup_info() to avoid helpers seems reasonable. it's only three arguments currently, having four wouldn't be a problem. add a 'int flags' argument and define a flag for 'BYPASS_HELPER'. ok, isn't this api change too intrusive to other netfilter parts? ip_nat_setup_info() is referenced 11 times on an unpatched 2.4.18. From my point of view, Linux kernel API's have always been changing. And a simple one-argument-change doesn't hurt anybody. The patch may contain a huge number of lines (since it's 11 function call changes) - but looking at it from an abstract point of view, there is nothing intrusive about it. A third solution would be to add new NFCT_ flag. Do you still prefer the flags argument? no, nfct again looks like a hack. This however wouldn't bypass the conntrack helper [which could already say INVALID because a packet doesn't match the layer5+ state of the connection, see for example the PPTP helper]. Don't forget that we have two conntrack entries if traffic is flown through a transparent proxy, and conntrack processing is done prior to NAT rewriting. Please tell me if I'm wrong, but CONNTRACK sees an unmodified PORT command assigned to a session with unmodified destination address. Oh, I didn't make myself clear. There are no bad interactions with NAT. But in case there really is an out-of-state packet, the conntrack helper would mark it INVALID - which might not be what you want in case of transparent proxying, where such state violation should be detected by the proxy itself. Bazsi -- Live long and prosper - Harald Welte / [EMAIL PROTECTED] http://www.gnumonks.org/ GCS/E/IT d- s-: a-- C+++ UL$ P+++ L$ E--- W- N++ o? K- w--- O- M+ V-- PS++ PE-- Y++ PGP++ t+ 5-- !X !R tv-- b+++ !DI !D G+ e* h--- r++ y+(*)
Re: TPROXY and original dest address question
On Thu, Mar 28, 2002 at 05:55:25PM +0100, Henrik Nordstrom wrote: an entry is removed from this table when 1) the socket associated with the entry is destroyed (iff a socket is associated with an entry) Ok. So there is integration between the tproxy table and the host IP stack somehow, to keep the TPROXY table in sync with the host IP stack. Nice. Kind of missing in conntrack.. Until now the only binding between the socket and the entry was the address of the local socket. This might have to be changed due to the problem you described below. 2) when a TCP rst is returned by the stack (happens only when a socket is not yet associated) Why this? And doesn't it allow for an easy DOS on TPROXY sessions? You should not be processing RST unless you are also processing TCP widows. Not all RST packets resets the session. Ah, I think I understand now. You only do this when there isn't yet a socket in the host IP stack. In such case it is needed. yes, an alternative would be a hook in the kernel which is called when a socket was not found to an incoming SYN. this is an ugly hack though. Sounds like it could be made to work for TCP. UDP is a bit different thou.. but there isn't that big need of a any connection table there, except for ICMP processing. For UDP I only want to do half-NAT, which means that it would be possible to send a UDP frame with a custom IP address, and receive one destined to somebody else. ICMP processing is needed when we send an UDP frame (with foreign source address), and the destination host returns an ICMP error to the sender. In Linux 2.2 we do the following as a transparent proxy with UDP traffic: * we have a sender socket, which we use to send packets with specified source AND destination address * prior to sending a packet we create, bind and connect a socket to a destination we are sending packets to (this socket receives ICMP errors) A similar approach is doable: * the source address is specified in a control message of sendmsg() * this doesn't create a translation entry in TPROXY * a separate socket is created, and a setsockopt is issued, which places socket related information into the translation table * when an ICMP error is received, the second socket is found, and ICMP error is rewritten accordingly * if no specific socket is found, it is forwarded (and dropped on the forward chain) Hmm.. regarding ICMP. How do you plan on handle ICMP from the host stack without TCP window tracking? Problem: There may be multiple sessions from the same client IP,PORT to the same PORT on multiple servers, and after NAT there isn't sufficient information to distinguish these by the addressing alone. 10.0.1.4:52346 - 192.168.96.32:80 10.0.1.4:52346 - 192.168.84.253:80 10.0.1.4:52346 - 176.16.48.52:80 The problem is much more evident if you look at UDP traffic, but exists for TCP as well. For TCP you can easily see this if there is multiple clients behind a NAT gateway (for example netfilter SNAT). Hmm.. this problem probably also applies to the de-NAT:ing of traffic, but there you can probably get by by querying the socket for the real source address (original destination address). Hmm... this is a real problem, but I only see this occuring in our case when we redirect a session, and responses must be de-NATed. In this case however skb-sk is unique (except for maybe SYN-ACK, because socket is not created until the three-way handshake is fully completed) -- Bazsi PGP info: KeyID 9AF8D0A9 Fingerprint CD27 CFB0 802C 0944 9CFD 804E C82C 8EB1
Re: TPROXY and original dest address question
It doesn't handle currently any of them. Fragmentation can be solved by defragmenting incoming packets. (they are destined to the local ip stack anyway) Defragmentation is defenitely needed for this thing to be used in production. For experimentation conntrack can be used to defragment.. In my previous attempts to forward port the transparent proxy features of 2.2, I simply used ip_defrag(skb), which returned non-NULL when a full fragment was reassembled. ICMP can be handled in the prerouting hook looking up possible transparent proxy entries. Where is the possible transparent proxy entries defined? Internally in TPROXY, or in the host IP stack socket table? in TPROXY. I guess this would be the rule table telling what should be diverted by TPROXY, which from my understanding would be your iptables ruleset... No. I have -- Bazsi PGP info: KeyID 9AF8D0A9 Fingerprint CD27 CFB0 802C 0944 9CFD 804E C82C 8EB1
Re: TPROXY and original dest address question
Balazs Scheidler wrote: Where is the possible transparent proxy entries defined? Internally in TPROXY, or in the host IP stack socket table? in TPROXY. Is TPROXY is a stand-alone netfilter module, not a iptables target? I thought it was a iptables target, but from your answer it seems like it should be a netfilter module on it's own.. Regards Henrik
Re: TPROXY and original dest address question
On Thu, Mar 28, 2002 at 04:02:46PM +0100, Henrik Nordstrom wrote: Balazs Scheidler wrote: Where is the possible transparent proxy entries defined? Internally in TPROXY, or in the host IP stack socket table? in TPROXY. I guess this would be the rule table telling what should be diverted by TPROXY, which from my understanding would be your iptables ruleset... No. I have You have what? Seems to be part of the message missing here..?? Yes, sorry. There's a translation table in TPROXY independent from the tproxy iptables table. The rules are in the iptables table called 'tproxy', and contains one transparent proxy rule for each service needed. As a connection is established, a new entry is added to the translation table with: remote addr/remote port, original dest/original port, local dest/local port. Then both the prerouting and the local output hooks perform translation of the packet flow according to the translation table. In a sence this table is similar to the conntrack tables, with the exception that the primary focus is to assign packet endpoints with local sockets, identified by their own IP/port pair. Thus the connection between a redirected session and a local socket is not the socket layer, but this translation table, therefore no packet with foreign IP address enter the networking core. -- Bazsi PGP info: KeyID 9AF8D0A9 Fingerprint CD27 CFB0 802C 0944 9CFD 804E C82C 8EB1
Re: TPROXY and original dest address question
On Thu, Mar 28, 2002 at 04:39:51PM +0100, Henrik Nordstrom wrote: Thanks. Explains it quite well. So there is yet another state table involved here. Now I am a little confused. What exacly is it that makes this new state table better suited for the job than conntrack? because we don't do full TCP tracking, and our NAT is quite limited. (only DNAT, and only to local IP stack). And in addition entries are not timeouted from the table. a new entry is added to this table when 1) a TPROXY destination is encountered 2) when a socket is 'bound' to a foreign address (either for listening and connecting) an entry is removed from this table when 1) the socket associated with the entry is destroyed (iff a socket is associated with an entry) 2) when a TCP rst is returned by the stack (happens only when a socket is not yet associated) -- Bazsi PGP info: KeyID 9AF8D0A9 Fingerprint CD27 CFB0 802C 0944 9CFD 804E C82C 8EB1
Re: TPROXY and original dest address question
Balazs Scheidler wrote: because we don't do full TCP tracking, and our NAT is quite limited. (only DNAT, and only to local IP stack). And in addition entries are not timeouted from the table. a new entry is added to this table when 1) a TPROXY destination is encountered 2) when a socket is 'bound' to a foreign address (either for listening and connecting) Ok. an entry is removed from this table when 1) the socket associated with the entry is destroyed (iff a socket is associated with an entry) Ok. So there is integration between the tproxy table and the host IP stack somehow, to keep the TPROXY table in sync with the host IP stack. Nice. Kind of missing in conntrack.. 2) when a TCP rst is returned by the stack (happens only when a socket is not yet associated) Why this? And doesn't it allow for an easy DOS on TPROXY sessions? You should not be processing RST unless you are also processing TCP widows. Not all RST packets resets the session. Ah, I think I understand now. You only do this when there isn't yet a socket in the host IP stack. In such case it is needed. Sounds like it could be made to work for TCP. UDP is a bit different thou.. but there isn't that big need of a any connection table there, except for ICMP processing. Hmm.. regarding ICMP. How do you plan on handle ICMP from the host stack without TCP window tracking? Problem: There may be multiple sessions from the same client IP,PORT to the same PORT on multiple servers, and after NAT there isn't sufficient information to distinguish these by the addressing alone. 10.0.1.4:52346 - 192.168.96.32:80 10.0.1.4:52346 - 192.168.84.253:80 10.0.1.4:52346 - 176.16.48.52:80 The problem is much more evident if you look at UDP traffic, but exists for TCP as well. For TCP you can easily see this if there is multiple clients behind a NAT gateway (for example netfilter SNAT). Hmm.. this problem probably also applies to the de-NAT:ing of traffic, but there you can probably get by by querying the socket for the real source address (original destination address). Regards Henrik
Re: TPROXY and original dest address question
On Tue, Mar 26, 2002 at 04:21:04PM +0100, Balazs Scheidler wrote: Hi, I found some time to get back to my transparent proxy support for Netfilter. cool. We'd really like to see this getting forward. - TPROXY target redirects a session - the original destination address/port number is stored in the IPCB() part of the skb - as soon as the socket is created this address/port number is copied into sk-tp_pinfo.af_tcp (struct tcp_opt) This would happen in tcp_v4_hnd_req() - this information is queried by the application using a getsockopt call to fetch the original destination address, the getsockopt can be implemented by registering an nf_sockopt_ops I'd like to have the core-members advice, is this a good way? Harald? This looks fine to me, but I'm not as much into the sockets code as others are. If you want to make it really correct, I'd send that Mail to the [EMAIL PROTECTED] Mailinglist. David Miller, Andi Kleen and Alexey Kuznetsov (the networking gods) are hanging out on that list, so you might get some comments related the 'abuse' of tp_pinfo.af_tcp and IPCB() from them. Based on their reaction you will see if there is a need to change something or if they would like something like this in the kernel. Bazsi -- Live long and prosper - Harald Welte / [EMAIL PROTECTED] http://www.gnumonks.org/ GCS/E/IT d- s-: a-- C+++ UL$ P+++ L$ E--- W- N++ o? K- w--- O- M+ V-- PS++ PE-- Y++ PGP++ t+ 5-- !X !R tv-- b+++ !DI !D G+ e* h--- r++ y+(*)
Re: TPROXY and original dest address question
Please don't forget UDP. For UDP you need to save the original destination, and then implement a control message extension for sending this to userspace together with the packet in response to a recvmsg() call, or hack the kernel to return the original destination in IP_PKTINFO (would be the most natural I think). See earlier post from me for a lengthy discussion on how one can do this in the current NAT scheme. If you same the address in the actual skb then this becomes even easier. In case of IP_PKTINFO only only two lines.. Reviewing the existing sockopt options the following seems like the correct calls: * For TCP, return the original destination in getsockopt(SOL_IP, IP_PKTOPTIONS...) * For UCP, return the original destination in the IP_PKTINFO recvmsg control message, and if possible, use the same to allow the application to control the source address when sending packets using sendmsg(). What I do not quite get is how TPROXY is supposed to handle return traffic, fragmented packets or ICMP, if you are doing stateless NAT. Also, who is responsible for making sure the application protocol is NAT:ed properly in TPROXY. For example FTP PASV. Is it the kernel, or is it the userspace proxy responsibility to get the correct (foreign) IP address in such case? And what about related connections such as an FTP data channel? Sorry if I am making things overly complex here.. In my view (as an application developer, not netfilter hacker) the problems with the standard netfilter approach are: 1. Cannot easily support non-local bind, to allow the userspace proxy application to masquerade as the client 2. Cannot get the original destination of a redirected UDP packet in an easy manner (might be possible by parsing /proc/net/ip_conntrack and quess which is the correct connection...) 3. conntrack adds yet another state table, with a bunch of new DOS conditions one must worry about.. Regards Henrik
Re: TPROXY and original dest address question
On Wed, Mar 27, 2002 at 02:56:56PM +0100, Henrik Nordstrom wrote: Please don't forget UDP. I won't. I definitely want UDP as well. For UDP you need to save the original destination, and then implement a control message extension for sending this to userspace together with the packet in response to a recvmsg() call, or hack the kernel to return the original destination in IP_PKTINFO (would be the most natural I think). See earlier post from me for a lengthy discussion on how one can do this in the current NAT scheme. If you same the address in the actual skb then this becomes even easier. In case of IP_PKTINFO only only two lines.. Reviewing the existing sockopt options the following seems like the correct calls: * For TCP, return the original destination in getsockopt(SOL_IP, IP_PKTOPTIONS...) * For UCP, return the original destination in the IP_PKTINFO recvmsg control message, and if possible, use the same to allow the application to control the source address when sending packets using sendmsg(). ok. I originally wanted to have separate getsockopt calls, but it's better to use already established ones. The only possible problem that I need to tocuh the networking core which I want to avoid touching. What I do not quite get is how TPROXY is supposed to handle return traffic, fragmented packets or ICMP, if you are doing stateless NAT. It doesn't handle currently any of them. Fragmentation can be solved by defragmenting incoming packets. (they are destined to the local ip stack anyway) ICMP can be handled in the prerouting hook looking up possible transparent proxy entries. Also, who is responsible for making sure the application protocol is NAT:ed properly in TPROXY. For example FTP PASV. Is it the kernel, or is it the userspace proxy responsibility to get the correct (foreign) IP address in such case? And what about related connections such as an FTP data channel? Of course the proxy itself. How it currently works in Zorp (with kernel 2.2): * the FTP command channel is redirected to the proxy * when a PASV command is sent, a non-local bind is performed to bind to the server's IP random port * the PASV reply is rewritten to contain information about the allocated port * the data channel is established when the client connects to the socket the firewall allocated * the connection to the server is then established by the proxy Sorry if I am making things overly complex here.. In my view (as an application developer, not netfilter hacker) the problems with the standard netfilter approach are: 1. Cannot easily support non-local bind, to allow the userspace proxy application to masquerade as the client 2. Cannot get the original destination of a redirected UDP packet in an easy manner (might be possible by parsing /proc/net/ip_conntrack and quess which is the correct connection...) 3. conntrack adds yet another state table, with a bunch of new DOS conditions one must worry about.. conntrack will not be involved in TPROXY, though I want them to interoperate. -- Bazsi PGP info: KeyID 9AF8D0A9 Fingerprint CD27 CFB0 802C 0944 9CFD 804E C82C 8EB1
Re: TPROXY
On Wed, Mar 27, 2002 at 04:17:53PM +0100, Jean-Michel Hemstedt wrote: On Tuesdayen den 26 March 2002 16.33, Balazs Scheidler wrote: The user is not capable of deciding whether a certificate presented to him really belongs to the given server. They simply press 'continue' without thinking that the server they are communicating with is fake. Of course if you AND your users know what the hell a certificate is, they can decide but I think you are a minority. We are far from TPROXY, but here is my point of view: - HTTPS decrypting proxy is an (mitma) alternative if you want to block all CONNECT operations in your proxy. But it sounds like an absuse protection against inside users. And unfortunately, for the user itself, as mentionned above, it will block services such as home banking as well. * If you allow HTTPS transparently, CONNECT is not invoked. * If you use a non-transparent HTTP proxy, the client requests a CONNECT from the proxy which in turn connects to the web server opening a hole in your firewall. You have three options: 1) enable SSL traffic without being able to verify its contents (Nimda through SSL anyone?) 2) disable SSL completely 3) use a decrypting SSL proxy with content verification - If your proxy allows CONNECT requests, then virtually anything can pass through it, and HTTPS decrypting proxy does not make sense. why? I attach a decrypting HTTPS proxy when a CONNECT request is encountered, as follows: * Nontransparent HTTP proxy receives a CONNECT www.homebank.hu:443 HTTP/1.0 request * Http proxy stacks in an SSL proxy which receives the datastream after CONNECT * The SSL proxy decrypts traffic and stacks in a HTTP proxy again: [nontransparent HTTP proxy] | [decrypting SSL proxy invoked after CONNECT] | [stacked transparent HTTP proxy] The above scenario is completely doable with Zorp. Then, if you are really concerned by insider attacks, what about a session/tunnel timer which could be a possible (ugly) protection against wormhole kinds of attacks, without invalidating ssl? IMHO it's not about insider attacks, its about incompetent clients who start trojan horses, get viruses and accept certificates without even knowing what it means. Decrypting on the firewall is not invalidating SSL. SSL is authentication+integrity protection+crypted traffic. Authentication is performed by the firewall, integrity protection is performed and the whole traffic is crypted. Authentication is moved from the client computer to the firewall, which checks it more strictly than most clients do. And the firewall accepts a certificate based on its policy. No user should override this. Of course when moving the certificate authentication is not an option (because client certificates are used, which are stored on a hardware token), you can still use a 'hole', but this can be limited to a few addresses only. btw: I think this discussion is off-topic on netfilter-devel, so we might continue our discussion in private. -- Bazsi PGP info: KeyID 9AF8D0A9 Fingerprint CD27 CFB0 802C 0944 9CFD 804E C82C 8EB1
Re: TPROXY
On Wed, Mar 27, 2002 at 10:15:56AM +0100, Henrik Nordstrom wrote: On Tuesdayen den 26 March 2002 16.33, Balazs Scheidler wrote: Providing a client certificate to the server is not very common, if it is required a tunnel can be opened to that _specific_ server, and nothing else. So using a real decrypting HTTPS proxy for general https traffic, and opening holes to specific destinations is definitely more secure than a simple 'pass-through' hole in the firewall. You missed the point here. Using a decryption HTTPS proxy invalidates both the use of client certificates AND the use of server certificates, which makes the use of SSL somewhat pointless. Further, unless the proxy runs it's own CA trusted by the browsers then the users will always be warned that the server certificate is invalid when using such proxy. I think you missed the point here. Of course the firewall verifies the server's certificate using its own trusted list of CAs. The user is not capable of deciding whether a certificate presented to him really belongs to the given server. They simply press 'continue' without thinking that the server they are communicating with is fake. Of course if you AND your users know what the hell a certificate is, they can decide but I think you are a minority. We are far from TPROXY, but here is my point of view: - HTTPS decrypting proxy is an (mitma) alternative if you want to block all CONNECT operations in your proxy. But it sounds like an absuse protection against inside users. And unfortunately, for the user itself, as mentionned above, it will block services such as home banking as well. - If your proxy allows CONNECT requests, then virtually anything can pass through it, and HTTPS decrypting proxy does not make sense. Then, if you are really concerned by insider attacks, what about a session/tunnel timer which could be a possible (ugly) protection against wormhole kinds of attacks, without invalidating ssl? -jmhe-
Re: TPROXY and original dest address question
On Wednesday 27 March 2002 16.17, Jean-Michel Hemstedt wrote: - If your proxy allows CONNECT requests, then virtually anything can pass through it, and HTTPS decrypting proxy does not make sense. A proxy can in theory verify that the supposedly SSL stream looks like a SSL stream and not something else.. The SSL and TLS data streams are quite structured. It doesn't handle currently any of them. Fragmentation can be solved by defragmenting incoming packets. (they are destined to the local ip stack anyway) Defragmentation is defenitely needed for this thing to be used in production. For experimentation conntrack can be used to defragment.. ICMP can be handled in the prerouting hook looking up possible transparent proxy entries. Where is the possible transparent proxy entries defined? Internally in TPROXY, or in the host IP stack socket table? I guess this would be the rule table telling what should be diverted by TPROXY, which from my understanding would be your iptables ruleset... Also, who is responsible for making sure the application protocol is NAT:ed properly in TPROXY. Of course the proxy itself. Good. conntrack will not be involved in TPROXY, though I want them to interoperate. Of course. Just mentioned it as a reference on why I see that one cannot really use netfilter NAT for truly transparent proxying as it is today. Regards Henrik
Re: TPROXY
On Wed, Mar 20, 2002 at 12:12:24AM +0100, Henrik Nordstrom wrote: 2) the 50080/50443 applications rely on TPROXY framework and uses nonlocal_bind. Except that nonlocal_bind do not yet work in TPROXY, does it? not yet. Zorp supports HTTPS, but it doesn't encapsulate it into CONNECT. It simply decrypts ongoing traffic, checks HTTP within it, and sends it on reencrypted. But for this to work you'd need to run Zorp on your firewall (where it was meant to run) At the cost of totally invalidating SSL in terms of proxying. - Client can no longer verify the authenticity of the origin server further than the proxy. - Servers can no longer authenticate or verify the client. Typical man-in-the-middle scenario. I assume we are talking about what is nominated by the IEFT WREC group as surrogate servers rather than proxies here.. If not then decrypting proxied SSL traffic is a serious breach of security. Tunnelling SSL through firewalls _is_ a more serious breach of security. It is a full-speed covert channel. IRC and ICQ clients began to use such holes in the firewall to send IRC/ICQ traffic. Of course a proxy sitting between the client and the server means that peer certificates cannot be verified on the other peer. On the server side the firewall can perform this verification (and show a trusted certificate to the client) Providing a client certificate to the server is not very common, if it is required a tunnel can be opened to that _specific_ server, and nothing else. So using a real decrypting HTTPS proxy for general https traffic, and opening holes to specific destinations is definitely more secure than a simple 'pass-through' hole in the firewall. -- Bazsi PGP info: KeyID 9AF8D0A9 Fingerprint CD27 CFB0 802C 0944 9CFD 804E C82C 8EB1
Re: TPROXY
Henrik, just to recap the goal: I have: - non-proxy aware clients (not controlable) - non-transparent aware proxy (not controlable, and even not on Linux, it is not in-housed) an in the middle: - one (or more) default gateway, the netfilter box. = goal: 1) HTTP: rewrite the HTTP requests (PDU) so that they can be handled by the proxy. 2) HTTPS: insert the CONNECT transactions so that the proxy can create its https tunnel to the orig-server. (and there is no mitma issue) 3) for both: keep the source ip addresses of the clients in the modified forwarded packets, so that the proxy can do simple source based authentication (possibly with the collaboration of exteral elements such as radius, but athentication is out of scope here). I appreciate your propositions, but since we don't see the origin-server, since we are forced to pass the requests through the proxy, since the proxy is not controlable, since the PDU needs to be rewritten, and since the stream itself needs to be modified (https), none of them (CONNMARK or GRE tunnel) seems to be applicable. The big issue is point 3 above, given that 1 and 2 needs to be handled. nonlocal_bind or contextual SNAT could be the solutions... But my NF level of experience is too weak for the moment to see how it could be achieved, or how to reuse existing mechanisms. (i.e: how to make NAT and REDIRECT collaborate, or how to crack nonlocal_bind protection). best regards. - Original Message - From: Henrik Nordstrom [EMAIL PROTECTED] To: Jean-Michel Hemstedt [EMAIL PROTECTED]; Balazs Scheidler [EMAIL PROTECTED] Cc: [EMAIL PROTECTED] Sent: Wednesday, 20 March, 2002 00:12 Subject: Re: TPROXY [cannot claim I have been following the thread closely, mostly guessing on what you are actually trying to acheive here.. so I may be way off] On Tuesday 19 March 2002 12:19, Jean-Michel Hemstedt wrote: REDIRECT could work in case of collocated proxy, and only if we have control on the proxy, i.e. Apache; (btw: I'm curreltly trying to find a clean and reusable way to extend transparent HTTP mod_tprox and add HTTPS transp proxy to Apache for Linux). REDIRECT works only if the you have a user space proxy is running on the machine doing REDIRECT. This is per definition of REDIRECT. But I'm afraid REDIRECT doesn't fit for remote proxies which rely on the originam source ip ofthe client to perform some checks. In that case we need the 50080/50443 applications of your example to forward the modified requests to the remote proxy with the source.ip of the original client. If the remote proxy is on the same LAN segment or if you can set up a GRE tunnel or something similar to the proxy server then you can use CONNMARK for this purpose to route the packets unmodified to the proxy and then do the final interception there. When you see the NEW session in mangle, mark it, then use fwmark based routing to route the packets of that session to the close by proxy. 1) the 50080/50443 applications use libipt and for each new client request, before doing a new connect() to the remote proxy, they create a new iptable rule doing SNAT based on the --sport they choosed for their bind(). And when the connection is released, they remove the created rule. This solution is very inefficient, and not scalable. Yuck. I would rather go for a single daemon using a custom protocol to forward the information to the origin server, such as the (incidentally) named TPROXY extension I was once playing with for Squid, archived somewhere on my old Squid patches page http://devel.squid-cache.org/hno/patche-old.html on how to manage remote interception of traffic. But sure, this is a limitation of the transparent proxy capabilities of the current iptables framework. I think some aspects of SOCKS can also be used for this purpose. 2) the 50080/50443 applications rely on TPROXY framework and uses nonlocal_bind. Except that nonlocal_bind do not yet work in TPROXY, does it? 3) ??INTERCEPT?? = REDIRECT(PREROUTING)+SNAT(OUTPUT/POSTROUTING?) i.e: A:pclient1 [REDIRECT--dport80] Bserver:50080Bclient:pclient2 [SNAT(--to A:pclient)] C:80 = the INTERCEPT would REDIRECT the packets from the client to the local stack and pass a 'rdmark' to the user space application retreivable via getsockopt(rdmark). Then, the application rewrites the packets and in order to forward them to the remote proxy, it creates a new client socket to the remote-proxy and uses setsockopt(rdmark) to instruct netfilter to do SNAT on the outgoing packets (OUPUT/POSTROUTING?). Netfilter uses the 'rdmark' to retreive from the redirect table the '--to' information (the source.ip before the redirect). When a packet comes back from the remote-proxy the reverse SNAT redirects the packets to the local client, which pass the packet to the local server which sends back to the original client the modified packets... Very much
Re: TPROXY
Right. For this with iptables the standard solution is to run a small proxy on the iptables box, and have iptables extended to allow this proxy to control the source address of outgoing connections. Unfortunately this functionality isn't easily achievable in iptables at the moment. iptables can reliably intercept TCP sessions, but it cannot easily spoof outgoing connections as the original client or reliably intercept UDP sessions. This is from my understanding the main reasons to the TPROXY work. An option which is readily available and proven is to go for Linux-2.2+ipchains+transparent proxy kernel option, all part of the standard kernel distribution. This allows a proxy running as root (or with CAP_NETADMIN I think) to freely assign the source address using non-local binds. I know that people have succeeded in adopting Squid to use the client's source address in such configurations. If running this on the gateway isn't an option then you can utilize the CONNMARK functionality to divert the to be proxied traffic to another box running the intermediary transparent proxy. Another option, working entirely within iptables, is to write a custom iptables NAT helper module doing the request transformation. For the SSL redirection this is quite simple, simply insert the CONNECT HTTP request initially in the data stream, but the HTTP redirection is somewhat more complex as you then need to account for persistent connections and possibly also transfer encodings of HTTP/1.1, and this again is somewhat beyond the capabilities of netfilter.. (netfilter NAT operates per packet, not that easily on TCP streams where data may cross packet boundaries). While the method of interception and client spoofing used in Linux-2.2 transparent proxy isn't well seen by the TCP/IP stack maintainers or the Netfilter developers, it really works well for dedicated transparent proxies. Regards Henrik Nordström On Wednesdayen den 20 March 2002 10.29, Jean-Michel Hemstedt wrote: Henrik, just to recap the goal: I have: - non-proxy aware clients (not controlable) - non-transparent aware proxy (not controlable, and even not on Linux, it is not in-housed) an in the middle: - one (or more) default gateway, the netfilter box. = goal: 1) HTTP: rewrite the HTTP requests (PDU) so that they can be handled by the proxy. 2) HTTPS: insert the CONNECT transactions so that the proxy can create its https tunnel to the orig-server. (and there is no mitma issue) 3) for both: keep the source ip addresses of the clients in the modified forwarded packets, so that the proxy can do simple source based authentication (possibly with the collaboration of exteral elements such as radius, but athentication is out of scope here).
Re: TPROXY
On Wednesday 20 March 2002 17:29, Jean-Michel Hemstedt wrote: I have: - non-proxy aware clients (not controlable) - non-transparent aware proxy (not controlable, and even not on Linux, it is not in-housed) an in the middle: - one (or more) default gateway, the netfilter box. = goal: 1) HTTP: rewrite the HTTP requests (PDU) so that they can be handled by the proxy. 2) HTTPS: insert the CONNECT transactions so that the proxy can create its https tunnel to the orig-server. (and there is no mitma issue) 3) for both: keep the source ip addresses of the clients in the modified forwarded packets, so that the proxy can do simple source based authentication (possibly with the collaboration of exteral elements such as radius, but athentication is out of scope here). How about transproxying to Squid on the netfilter box, and getting Squid to passthrough to the `real' proxy? Cheers; Leon
Re: TPROXY
On Wednesdayen den 20 March 2002 12.13, Leon Brooks wrote: How about transproxying to Squid on the netfilter box, and getting Squid to passthrough to the `real' proxy? Won't solve the issue of not hiding the clients real IP addresses. Regards Henrik Nordström Squid Developer Netfilter Hacker
Re: TPROXY
On Wednesdayen den 20 March 2002 12.13, Leon Brooks wrote: How about transproxying to Squid on the netfilter box, and getting Squid to passthrough to the `real' proxy? And also, Squid does not know how to intercept HTTPS traffic. But adding such functionality to Squid is trivial if needed. Regards Henrik
Re: TPROXY
Jean-Michel Hemstedt [EMAIL PROTECTED] wrote: = goal: 3) for both: keep the source ip addresses of the clients in the modified forwarded packets, so that the proxy can do simple source based authentication (possibly with the collaboration of exteral elements such as radius, but athentication is out of scope here). Assuming that a user-level gateway is an option, the patch/hack for IP_NONLOCAL_CONNECT posted to linux-kernel by Alexey Kuznetsov (http://www.uwsg.iu.edu/hypermail/linux/kernel/0109.0/0474.html) seems to work. --Per Hedeland [EMAIL PROTECTED]
Re: TPROXY
- Original Message - From: Balazs Scheidler [EMAIL PROTECTED] To: Jean-Michel Hemstedt [EMAIL PROTECTED] Sent: Tuesday, 19 March, 2002 08:50 Subject: Re: TPROXY On Wed, Mar 13, 2002 at 01:19:30PM +0100, Jean-Michel Hemstedt wrote: hello, I'm quite new to netfilter, and I would like to use/write an extension capable of rewriting HTTP/HTTPS requests from non-proxy aware clients to remote non-transparent aware proxy (the netfilter box being in the middle and acting as a default gw for both sides). This implies: - for HTTP: most HTTP requests methods (GET,POST,...) need to be rewritten with the full URL (taken from the non redirected ip.dst for HTTP/0.9 or from the 'Host' field for HTTP/1.x) - for HTTPS: *insert* an HTTP CONNECT transaction in the TCP stream (just after the TCP establishment), which means that the ip packets can't simply be redirected, unless playing with (cracking) the tcp.seq_num in netfilter. The first case is not a problem (kind of REDIRECT target) For the second case (HTTPS), I was thinking of using the ip_nonlocal_bind option, but I read in the kernel archives that the connect() was broken for non-local bind in 2.4.x. I would also avoid user space QUEUEing since I noticed that the throughput was simply divided by 2 (just for normal forwarding!). I think that your TPROXY target is well suited for the HTTPS case (terminating the tcp sessions of the client on the netfilter box and originating tcp session to the proxy from the netfilter box as if they were originating from the client, using a kind of *ip_nonlocal_bind* mechanism). right? TPROXY is not yet ready, it is lacking several important features. I posted it on the -devel list to receive feedback. Both of your problems can be solved by REDIRECT, you only need two different programs (or a single program performing both operations). Just listen on a random port (say 50080), and redirect all traffic to this port: iptables -t nat -A PREROUTING -p tcp -d 0/0 --dport 80 -j REDIRECT --to-port 50080 iptables -t nat -A PREROUTING -p tcp -d 0/0 --dport 443 -j REDIRECT --to-port 50443 REDIRECT could work in case of collocated proxy, and only if we have control on the proxy, i.e. Apache; (btw: I'm curreltly trying to find a clean and reusable way to extend transparent HTTP mod_tprox and add HTTPS transp proxy to Apache for Linux). But I'm afraid REDIRECT doesn't fit for remote proxies which rely on the originam source ip ofthe client to perform some checks. In that case we need the 50080/50443 applications of your example to forward the modified requests to the remote proxy with the source.ip of the original client. I see 3 possible ways to do that: 1) the 50080/50443 applications use libipt and for each new client request, before doing a new connect() to the remote proxy, they create a new iptable rule doing SNAT based on the --sport they choosed for their bind(). And when the connection is released, they remove the created rule. This solution is very inefficient, and not scalable. 2) the 50080/50443 applications rely on TPROXY framework and uses nonlocal_bind. 3) ??INTERCEPT?? = REDIRECT(PREROUTING)+SNAT(OUTPUT/POSTROUTING?) i.e: A:pclient1 [REDIRECT--dport80] Bserver:50080Bclient:pclient2 [SNAT(--to A:pclient)] C:80 = the INTERCEPT would REDIRECT the packets from the client to the local stack and pass a 'rdmark' to the user space application retreivable via getsockopt(rdmark). Then, the application rewrites the packets and in order to forward them to the remote proxy, it creates a new client socket to the remote-proxy and uses setsockopt(rdmark) to instruct netfilter to do SNAT on the outgoing packets (OUPUT/POSTROUTING?). Netfilter uses the 'rdmark' to retreive from the redirect table the '--to' information (the source.ip before the redirect). When a packet comes back from the remote-proxy the reverse SNAT redirects the packets to the local client, which pass the packet to the local server which sends back to the original client the modified packets... (PS: I don't think the MARK target is suited for that kind of mechanism) (PPS: the user space applications would move as LKM in a second phase) do you (or anyone else) see any other way to do it? One of your proxies will be listening on 50080 the other on 50443. The first performing non-transparent/transparent rewrite the other CONNECT encapsulation. By the way the first one is easy to do with Zorp. Its HttpProxy is able to rewrite server-requests to proxy-requests. CONNECT encapsulation is not supported I'm afraid. Have you received any feedback on your TPROXY target? not much. I hope I'll be able to contribute, but I'll first need to better understand what are all the features of Netfilter and how they can interact between each other... In the mean time, if you have any update, i'd like to have a look at it. Have you heard of any similar HTTPS-real-transp-proxy implementations
Re: TPROXY
[cannot claim I have been following the thread closely, mostly guessing on what you are actually trying to acheive here.. so I may be way off] On Tuesday 19 March 2002 12:19, Jean-Michel Hemstedt wrote: REDIRECT could work in case of collocated proxy, and only if we have control on the proxy, i.e. Apache; (btw: I'm curreltly trying to find a clean and reusable way to extend transparent HTTP mod_tprox and add HTTPS transp proxy to Apache for Linux). REDIRECT works only if the you have a user space proxy is running on the machine doing REDIRECT. This is per definition of REDIRECT. But I'm afraid REDIRECT doesn't fit for remote proxies which rely on the originam source ip ofthe client to perform some checks. In that case we need the 50080/50443 applications of your example to forward the modified requests to the remote proxy with the source.ip of the original client. If the remote proxy is on the same LAN segment or if you can set up a GRE tunnel or something similar to the proxy server then you can use CONNMARK for this purpose to route the packets unmodified to the proxy and then do the final interception there. When you see the NEW session in mangle, mark it, then use fwmark based routing to route the packets of that session to the close by proxy. 1) the 50080/50443 applications use libipt and for each new client request, before doing a new connect() to the remote proxy, they create a new iptable rule doing SNAT based on the --sport they choosed for their bind(). And when the connection is released, they remove the created rule. This solution is very inefficient, and not scalable. Yuck. I would rather go for a single daemon using a custom protocol to forward the information to the origin server, such as the (incidentally) named TPROXY extension I was once playing with for Squid, archived somewhere on my old Squid patches page http://devel.squid-cache.org/hno/patche-old.html on how to manage remote interception of traffic. But sure, this is a limitation of the transparent proxy capabilities of the current iptables framework. I think some aspects of SOCKS can also be used for this purpose. 2) the 50080/50443 applications rely on TPROXY framework and uses nonlocal_bind. Except that nonlocal_bind do not yet work in TPROXY, does it? 3) ??INTERCEPT?? = REDIRECT(PREROUTING)+SNAT(OUTPUT/POSTROUTING?) i.e: A:pclient1 [REDIRECT--dport80] Bserver:50080Bclient:pclient2 [SNAT(--to A:pclient)] C:80 = the INTERCEPT would REDIRECT the packets from the client to the local stack and pass a 'rdmark' to the user space application retreivable via getsockopt(rdmark). Then, the application rewrites the packets and in order to forward them to the remote proxy, it creates a new client socket to the remote-proxy and uses setsockopt(rdmark) to instruct netfilter to do SNAT on the outgoing packets (OUPUT/POSTROUTING?). Netfilter uses the 'rdmark' to retreive from the redirect table the '--to' information (the source.ip before the redirect). When a packet comes back from the remote-proxy the reverse SNAT redirects the packets to the local client, which pass the packet to the local server which sends back to the original client the modified packets... Very much sounds like CONNMARK is what you are after here.. Allows you to selectively reroute individual tracked sessions without needing to rely on NAT. But if you need to rewrite the payload then CONNMARK obviously won't help you.. Zorp supports HTTPS, but it doesn't encapsulate it into CONNECT. It simply decrypts ongoing traffic, checks HTTP within it, and sends it on reencrypted. But for this to work you'd need to run Zorp on your firewall (where it was meant to run) At the cost of totally invalidating SSL in terms of proxying. - Client can no longer verify the authenticity of the origin server further than the proxy. - Servers can no longer authenticate or verify the client. Typical man-in-the-middle scenario. I assume we are talking about what is nominated by the IEFT WREC group as surrogate servers rather than proxies here.. If not then decrypting proxied SSL traffic is a serious breach of security. Regards Henrik Nordström