From 51f4d36b6abd6c6b2fee4511a4727c84f1ae9431 Mon Sep 17 00:00:00 2001 From: Amos Jeffries Date: Sat, 21 Mar 2009 13:57:14 +1300 Subject: [PATCH] Shuffle PF interception into its own function. With this all of the transparent build options are independent, and may be used in any combination. Squid is no longer bound to the single-firewall interception support. NP: one small note the PF lookup is slightly weird due to its altering the local client address from the NAT information. --- src/ip/IpIntercept.cc | 114 ++++++++++++++++++++---------------------- src/ip/IpIntercept.h | 9 ++++ 2 files changed, 63 insertions(+), 60 deletions(-) diff --git a/src/ip/IpIntercept.cc b/src/ip/IpIntercept.cc index 57d0d282ce..39d8787bf6 100644 --- a/src/ip/IpIntercept.cc +++ b/src/ip/IpIntercept.cc @@ -294,73 +294,31 @@ IpIntercept::IpfInterception(int fd, const IpAddress &me, IpAddress &dst, int si return -1; } - int -IpIntercept::NatLookup(int fd, const IpAddress &me, const IpAddress &peer, IpAddress &client, IpAddress &dst) +IpIntercept::PfInterception(int fd, IpAddress &client, IpAddress &dst, int silent) { - /* --enable-linux-netfilter */ - /* --enable-ipfw-transparent */ - /* --enable-ipf-transparent */ -#if IPF_TRANSPARENT || LINUX_NETFILTER || IPFW_TRANSPARENT - - /* Netfilter and IPFW share almost identical lookup methods for their NAT tables. - * This allows us to perform a nice clean failover sequence for them. - */ - - client = me; - dst = peer; - - if ( !me.IsIPv4() ) return -1; - if ( !peer.IsIPv4() ) return -1; - -#if 0 - // Crop interception errors down to one per minute. - int silent = (squid_curtime - last_reported > 60 ? 0 : 1); -#else - // Show all interception errors. - int silent = 0; -#endif - - if (intercept_active) { - if ( IpfInterception(fd, me, client, silent) == 0) return 0; - if ( NetfilterInterception(fd, me, client, silent) == 0) return 0; - if ( IpfwInterception(fd, me, client, silent) == 0) return 0; - } - if (transparent_active) { - if ( NetfilterTransparent(fd, me, dst, silent) == 0) return 0; - } - - return -1; - -#elif PF_TRANSPARENT /* --enable-pf-transparent */ +#if PF_TRANSPARENT /* --enable-pf-transparent */ struct pfioc_natlook nl; static int pffd = -1; - if ( !me.IsIPv4() ) return -1; - if ( !peer.IsIPv4() ) return -1; - if (pffd < 0) pffd = open("/dev/pf", O_RDONLY); if (pffd < 0) { - if (squid_curtime - last_reported > 60) { - debugs(89, 1, "clientNatLookup: PF open failed: " << xstrerror()); + if (!silent) { + debugs(89, 1, HERE << "PF open failed: " << xstrerror()); last_reported = squid_curtime; } - return -1; - } - client.SetEmpty(); - memset(&nl, 0, sizeof(struct pfioc_natlook)); - peer.GetInAddr(nl.saddr.v4); - nl.sport = htons(peer.GetPort()); + dst.GetInAddr(nl.saddr.v4); + nl.sport = htons(dst.GetPort()); - me.GetInAddr(nl.daddr.v4); - nl.dport = htons(me.GetPort()); + client.GetInAddr(nl.daddr.v4); + nl.dport = htons(client.GetPort()); nl.af = AF_INET; nl.proto = IPPROTO_TCP; @@ -368,35 +326,71 @@ IpIntercept::NatLookup(int fd, const IpAddress &me, const IpAddress &peer, IpAdd if (ioctl(pffd, DIOCNATLOOK, &nl)) { if (errno != ENOENT) { - if (squid_curtime - last_reported > 60) { + if (!silent) { debugs(89, 1, "clientNatLookup: PF lookup failed: ioctl(DIOCNATLOOK)"); last_reported = squid_curtime; } - close(pffd); pffd = -1; } - - return -1; } else { - int natted = (me != nl.rdaddr.v4); + int natted = (client != nl.rdaddr.v4); client = nl.rdaddr.v4; client.SetPort(ntohs(nl.rdport)); if (natted) return 0; - else - return -1; } + debugs(89, 9, HERE << "address: client= " << client << ", dst= " << dst); -#else /* none of the transparent options configured */ - - debugs(89, 1, "WARNING: transparent proxying not supported"); +#endif /* --enable-pf-transparent */ return -1; +} + + +int +IpIntercept::NatLookup(int fd, const IpAddress &me, const IpAddress &peer, IpAddress &client, IpAddress &dst) +{ + /* --enable-linux-netfilter */ + /* --enable-ipfw-transparent */ + /* --enable-ipf-transparent */ + /* --enable-pf-transparent */ +#if IPF_TRANSPARENT || LINUX_NETFILTER || IPFW_TRANSPARENT || PF_TRANSPARENT + + /* Netfilter and IPFW share almost identical lookup methods for their NAT tables. + * This allows us to perform a nice clean failover sequence for them. + */ + + client = me; + dst = peer; + + if ( !me.IsIPv4() ) return -1; + if ( !peer.IsIPv4() ) return -1; + +#if 0 + // Crop interception errors down to one per minute. + int silent = (squid_curtime - last_reported > 60 ? 0 : 1); +#else + // Show all interception errors. + int silent = 0; +#endif + + if (intercept_active) { + if ( IpfInterception(fd, me, client, silent) == 0) return 0; + if ( NetfilterInterception(fd, me, client, silent) == 0) return 0; + if ( IpfwInterception(fd, me, client, silent) == 0) return 0; + if ( PfInterception(fd, client, dst, silent) == 0) return 0; + } + if (transparent_active) { + if ( NetfilterTransparent(fd, me, dst, silent) == 0) return 0; + } +#else /* none of the transparent options configured */ + debugs(89, 1, "WARNING: transparent proxying not supported"); #endif + return -1; } #if LINUX_TPROXY2 diff --git a/src/ip/IpIntercept.h b/src/ip/IpIntercept.h index 2ee72b8c79..dc5b8bbe62 100644 --- a/src/ip/IpIntercept.h +++ b/src/ip/IpIntercept.h @@ -116,6 +116,15 @@ private: */ int IpfInterception(int fd, const IpAddress &me, IpAddress &client, int silent); + /** + * perform Lookups on PF interception. + * + \param silent[in] 0 if errors are to be displayed. 1 if errors are to be hidden. + \retval 0 Successfuly located the new address. + \retval -1 An error occured during NAT lookups. + */ + int PfInterception(int fd, IpAddress &client, IpAddress &client, int silent); + int transparent_active; int intercept_active; -- 2.39.5