Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Nov 2008 22:17:17 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r185067 - in user/adrian/spoof_bind: sbin/ipfw share/man/man4 sys/conf sys/net sys/netinet
Message-ID:  <200811182217.mAIMHHjm090641@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Tue Nov 18 22:17:17 2008
New Revision: 185067
URL: http://svn.freebsd.org/changeset/base/185067

Log:
  Bring over Julian's non-local bind stuff into a subversion branch.

Modified:
  user/adrian/spoof_bind/sbin/ipfw/ipfw2.c
  user/adrian/spoof_bind/share/man/man4/ip.4
  user/adrian/spoof_bind/sys/conf/NOTES
  user/adrian/spoof_bind/sys/conf/options
  user/adrian/spoof_bind/sys/net/if_bridge.c
  user/adrian/spoof_bind/sys/netinet/in.h
  user/adrian/spoof_bind/sys/netinet/in_pcb.c
  user/adrian/spoof_bind/sys/netinet/in_pcb.h
  user/adrian/spoof_bind/sys/netinet/ip_fw.h
  user/adrian/spoof_bind/sys/netinet/ip_fw2.c
  user/adrian/spoof_bind/sys/netinet/ip_output.c

Modified: user/adrian/spoof_bind/sbin/ipfw/ipfw2.c
==============================================================================
--- user/adrian/spoof_bind/sbin/ipfw/ipfw2.c	Tue Nov 18 22:11:33 2008	(r185066)
+++ user/adrian/spoof_bind/sbin/ipfw/ipfw2.c	Tue Nov 18 22:17:17 2008	(r185067)
@@ -301,6 +301,7 @@ enum tokens {
 	TOK_ANTISPOOF,
 	TOK_IPSEC,
 	TOK_COMMENT,
+	TOK_FOR_ME,
 
 	TOK_PLR,
 	TOK_NOERROR,
@@ -433,6 +434,7 @@ struct _s_x rule_options[] = {
 	{ "uid",		TOK_UID },
 	{ "gid",		TOK_GID },
 	{ "jail",		TOK_JAIL },
+	{ "for-me",		TOK_FOR_ME },
 	{ "in",			TOK_IN },
 	{ "limit",		TOK_LIMIT },
 	{ "keep-state",		TOK_KEEPSTATE },
@@ -2042,6 +2044,10 @@ show_ipfw(struct ip_fw *rule, int pcwidt
 					    O_TAGGED);
 				break;
 
+			case O_FOR_ME:
+				printf(" for-me");
+				break;
+
 			default:
 				printf(" [opcode %d len %d]",
 				    cmd->opcode, cmd->len);
@@ -5663,6 +5669,10 @@ read_options:
 			ac--; av++;
 			break;
 
+		case TOK_FOR_ME:
+			fill_cmd(cmd, O_FOR_ME, 0, 0);
+			break;
+
 		default:
 			errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
 		}

Modified: user/adrian/spoof_bind/share/man/man4/ip.4
==============================================================================
--- user/adrian/spoof_bind/share/man/man4/ip.4	Tue Nov 18 22:11:33 2008	(r185066)
+++ user/adrian/spoof_bind/share/man/man4/ip.4	Tue Nov 18 22:17:17 2008	(r185067)
@@ -292,6 +292,29 @@ cmsg_level = IPPROTO_IP
 cmsg_type = IP_RECVIF
 .Ed
 .Pp
+If the
+.Dv IP_NONLOCALOK
+options is set then the checking of local bind addresses against addresses
+assigned to local interfaces is disabled.
+The kernel must have been compiled with the
+.Dv IP_NONLOCALBIND option, and the sysctl
+.Va net.inet.ip.nonlocalok
+should be set to 1.
+The option needs to be set on the socket before the
+.Xr bind 2
+system call is used on it.
+.Bd -literal
+u_char spoofing = 1;   /* 0 = disable (default), 1 = enable */
+
+setsockopt(s, IPPROTO_IP, IP_NONLOCALOK, &spoofing, sizeof(spoofing));
+ret = bind (...);
+.Ed
+.Pp
+This behaviour is not for general use and is
+included for use in servers that are implementing fully
+transparent proxies. Use of this option on general purpose
+systems is strongly discouraged.
+.Pp
 .Dv IP_PORTRANGE
 may be used to set the port range used for selecting a local port number
 on a socket with an unspecified (zero) port number.

Modified: user/adrian/spoof_bind/sys/conf/NOTES
==============================================================================
--- user/adrian/spoof_bind/sys/conf/NOTES	Tue Nov 18 22:11:33 2008	(r185066)
+++ user/adrian/spoof_bind/sys/conf/NOTES	Tue Nov 18 22:17:17 2008	(r185067)
@@ -633,6 +633,14 @@ options 	ALTQ_PRIQ	# Priority Queueing
 options 	ALTQ_NOPCC	# Required if the TSC is unusable
 options 	ALTQ_DEBUG
 
+# IP optional behaviour.
+# IP_NONLOCALBIND disables the check that bind() usually makes that the
+# Address is one that is assigned to an interface on this machine.
+# It allows transparent proxies to pretend to be other machines.
+# How the packet GET to that machine is a problem solved elsewhere,
+# smart routers, ipfw fwd, etc.
+options        IP_NONLOCALBIND		#Allow impersonation for proxies.
+
 # netgraph(4). Enable the base netgraph code with the NETGRAPH option.
 # Individual node types can be enabled with the corresponding option
 # listed below; however, this is not strictly necessary as netgraph

Modified: user/adrian/spoof_bind/sys/conf/options
==============================================================================
--- user/adrian/spoof_bind/sys/conf/options	Tue Nov 18 22:11:33 2008	(r185066)
+++ user/adrian/spoof_bind/sys/conf/options	Tue Nov 18 22:17:17 2008	(r185067)
@@ -392,6 +392,7 @@ IPFIREWALL_VERBOSE	opt_ipfw.h
 IPFIREWALL_VERBOSE_LIMIT	opt_ipfw.h
 IPSEC			opt_ipsec.h
 IPSEC_DEBUG		opt_ipsec.h
+IP_NONLOCALBIND		opt_inet.h
 IPSEC_FILTERTUNNEL	opt_ipsec.h
 IPSTEALTH
 IPX

Modified: user/adrian/spoof_bind/sys/net/if_bridge.c
==============================================================================
--- user/adrian/spoof_bind/sys/net/if_bridge.c	Tue Nov 18 22:11:33 2008	(r185066)
+++ user/adrian/spoof_bind/sys/net/if_bridge.c	Tue Nov 18 22:17:17 2008	(r185067)
@@ -2938,6 +2938,10 @@ bridge_pfil(struct mbuf **mp, struct ifn
 	struct ip *ip;
 	struct llc llc1;
 	u_int16_t ether_type;
+	int is_ip = 0;
+#ifdef IPFIREWALL_FORWARD
+	struct m_tag *fwd_tag;
+#endif
 
 	snap = 0;
 	error = -1;	/* Default error if not error == 0 */
@@ -2997,6 +3001,7 @@ bridge_pfil(struct mbuf **mp, struct ifn
 #ifdef INET6
 		case ETHERTYPE_IPV6:
 #endif /* INET6 */
+			is_ip = 1;
 			break;
 		default:
 			/*
@@ -3057,6 +3062,25 @@ bridge_pfil(struct mbuf **mp, struct ifn
 		if (*mp == NULL)
 			return (error);
 
+#ifdef IPFIREWALL_FORWARD
+		/*
+		 * Did the firewall want to forward it somewhere?
+		 * If so, let the ip stack handle it.
+		 */
+		if (i == 0 && args.next_hop != NULL && is_ip /* && src != NULL */) {
+			fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, sizeof(struct sockaddr_in),
+			    M_NOWAIT);
+			if (fwd_tag == NULL)
+				goto drop;
+			bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in));
+			m_tag_prepend(*mp, fwd_tag);
+			if (in_localip(args.next_hop->sin_addr))
+				(*mp)->m_flags |= M_FASTFWD_OURS;
+			ether_demux(src, *mp);
+			return (NULL);
+		}
+#endif
+
 		if (DUMMYNET_LOADED && (i == IP_FW_DUMMYNET)) {
 
 			/* put the Ethernet header back on */

Modified: user/adrian/spoof_bind/sys/netinet/in.h
==============================================================================
--- user/adrian/spoof_bind/sys/netinet/in.h	Tue Nov 18 22:11:33 2008	(r185066)
+++ user/adrian/spoof_bind/sys/netinet/in.h	Tue Nov 18 22:17:17 2008	(r185067)
@@ -441,6 +441,7 @@ __END_DECLS
 #define	IP_FAITH		22   /* bool; accept FAITH'ed connections */
 
 #define	IP_ONESBCAST		23   /* bool: send all-ones broadcast */
+#define	IP_NONLOCALOK		24   /* allow bind to spoof other machines */
 
 #define	IP_FW_TABLE_ADD		40   /* add entry */
 #define	IP_FW_TABLE_DEL		41   /* delete entry */

Modified: user/adrian/spoof_bind/sys/netinet/in_pcb.c
==============================================================================
--- user/adrian/spoof_bind/sys/netinet/in_pcb.c	Tue Nov 18 22:11:33 2008	(r185066)
+++ user/adrian/spoof_bind/sys/netinet/in_pcb.c	Tue Nov 18 22:17:17 2008	(r185067)
@@ -35,6 +35,7 @@
 __FBSDID("$FreeBSD$");
 
 #include "opt_ddb.h"
+#include "opt_inet.h"
 #include "opt_ipsec.h"
 #include "opt_inet6.h"
 #include "opt_mac.h"
@@ -343,7 +344,11 @@ in_pcbbind_setup(struct inpcb *inp, stru
 		} else if (sin->sin_addr.s_addr != INADDR_ANY) {
 			sin->sin_port = 0;		/* yech... */
 			bzero(&sin->sin_zero, sizeof(sin->sin_zero));
-			if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
+			if (
+#if defined(IP_NONLOCALBIND)
+			    ((inp->inp_flags & INP_NONLOCALOK) == 0) &&
+#endif
+			    (ifa_ifwithaddr((struct sockaddr *)sin) == 0))
 				return (EADDRNOTAVAIL);
 		}
 		laddr = sin->sin_addr;

Modified: user/adrian/spoof_bind/sys/netinet/in_pcb.h
==============================================================================
--- user/adrian/spoof_bind/sys/netinet/in_pcb.h	Tue Nov 18 22:11:33 2008	(r185066)
+++ user/adrian/spoof_bind/sys/netinet/in_pcb.h	Tue Nov 18 22:17:17 2008	(r185067)
@@ -396,6 +396,8 @@ void 	inp_4tuple_get(struct inpcb *inp, 
 #define	INP_FAITH		0x200	/* accept FAITH'ed connections */
 #define	INP_RECVTTL		0x400	/* receive incoming IP TTL */
 #define	INP_DONTFRAG		0x800	/* don't fragment packet */
+#define	INP_NONLOCALOK		0x1000	/* Allow bind to spoof any address */
+					/* - requires options IP_NONLOCALBIND */
 
 #define IN6P_IPV6_V6ONLY	0x008000 /* restrict AF_INET6 socket for v6 */
 

Modified: user/adrian/spoof_bind/sys/netinet/ip_fw.h
==============================================================================
--- user/adrian/spoof_bind/sys/netinet/ip_fw.h	Tue Nov 18 22:11:33 2008	(r185066)
+++ user/adrian/spoof_bind/sys/netinet/ip_fw.h	Tue Nov 18 22:17:17 2008	(r185067)
@@ -174,6 +174,7 @@ enum ipfw_opcodes {		/* arguments (4 byt
 
 	O_TAG,   		/* arg1=tag number */
 	O_TAGGED,		/* arg1=tag number */
+	O_FOR_ME,		/* check for a PCB here for this packet */
 
 	O_SETFIB,		/* arg1=FIB number */
 	O_FIB,			/* arg1=FIB desired fib number */

Modified: user/adrian/spoof_bind/sys/netinet/ip_fw2.c
==============================================================================
--- user/adrian/spoof_bind/sys/netinet/ip_fw2.c	Tue Nov 18 22:11:33 2008	(r185066)
+++ user/adrian/spoof_bind/sys/netinet/ip_fw2.c	Tue Nov 18 22:17:17 2008	(r185067)
@@ -2068,6 +2068,46 @@ check_uidgid(ipfw_insn_u32 *insn, int pr
 }
 
 /*
+ * This function looks to see if the packet (regardless of direction)
+ * is destined for a socket on this machine.  This is regardless of
+ * whether the address of the socket is a legal address of this
+ * machine or not.  This is used for transparent proxying where
+ * the proxy masquerades as both the server and the client.
+ * It is not really needed if the IP_NONLOCALBIND is not dependent
+ * on that.  It is not quite the same as 'from any to me'.
+ * in that it checks ports too and doesn't check if the address
+ * is 'legally owned by this machine.  Do NOT insist there is still
+ * a socket..  It could be timing out.  It IS STILL OURS.
+ * XXX check whether we should only match if there is a
+ * socket on the pcb.
+ */
+static int
+packet_for_me(ipfw_insn_u32 *insn,
+    int proto,
+    struct in_addr dst_ip, u_int16_t dst_port,
+    struct in_addr src_ip, u_int16_t src_port )
+{
+	struct inpcbinfo *pi;
+	int wildcard;
+	struct inpcb *pcb;
+
+	if (proto == IPPROTO_TCP) {
+		wildcard = 0;
+		pi = &tcbinfo;
+	} else if (proto == IPPROTO_UDP) {
+		wildcard = INPLOOKUP_WILDCARD;
+		pi = &udbinfo;
+	} else {
+		return (0);
+	}
+	INP_INFO_RLOCK(pi);
+	pcb = in_pcblookup_hash(pi, src_ip, htons(src_port),
+	    dst_ip, htons(dst_port), wildcard, NULL);
+	INP_INFO_RUNLOCK(pi);
+	return (pcb?1:0);
+}
+
+/*
  * The main check routine for the firewall.
  *
  * All arguments are in args so we can modify them and return them
@@ -2090,6 +2130,7 @@ check_uidgid(ipfw_insn_u32 *insn, int pr
  *	args->next_hop	Socket we are forwarding to (out).
  *	args->f_id	Addresses grabbed from the packet (out)
  * 	args->cookie	a cookie depending on rule action
+ *	args->inp	A pcb associated with a packet if known
  *
  * Return value:
  *
@@ -2604,6 +2645,24 @@ check_body:
 						    &ugid_lookup, args->inp);
 				break;
 
+			case O_FOR_ME:
+				/*
+				 * We only check offset == 0 && TCP or UDP
+				 * as this ensures that we have a
+				 * packet with the ports info.
+				 */
+				if (offset!=0)
+					break;
+				if (is_ipv6) /* XXX to be fixed later */
+					break;
+				if (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
+				match = packet_for_me(
+				    (ipfw_insn_u32 *)cmd,
+				    proto,
+				    dst_ip, dst_port,
+				    src_ip, src_port );
+				break;
+
 			case O_RECV:
 				match = iface_match(m->m_pkthdr.rcvif,
 				    (ipfw_insn_if *)cmd);
@@ -3294,8 +3353,11 @@ check_body:
 			case O_FORWARD_IP: {
 				struct sockaddr_in *sa;
 				sa = &(((ipfw_insn_sa *)cmd)->sa);
+/* XXX julian's patch disabled this; "why" needs to be thought about. -adrian */
+#if 0
 				if (args->eh)	/* not valid on layer2 pkts */
 					break;
+#endif
 				if (!q || dyn_dir == MATCH_FORWARD) {
 					if (sa->sin_addr.s_addr == INADDR_ANY) {
 						bcopy(sa, &args->hopstore,
@@ -3814,6 +3876,7 @@ check_ipfw_struct(struct ip_fw *rule, in
 		case O_PROBE_STATE:
 		case O_KEEP_STATE:
 		case O_PROTO:
+		case O_FOR_ME:
 		case O_IP_SRC_ME:
 		case O_IP_DST_ME:
 		case O_LAYER2:

Modified: user/adrian/spoof_bind/sys/netinet/ip_output.c
==============================================================================
--- user/adrian/spoof_bind/sys/netinet/ip_output.c	Tue Nov 18 22:11:33 2008	(r185066)
+++ user/adrian/spoof_bind/sys/netinet/ip_output.c	Tue Nov 18 22:17:17 2008	(r185067)
@@ -33,6 +33,7 @@
 __FBSDID("$FreeBSD$");
 
 #include "opt_ipfw.h"
+#include "opt_inet.h"
 #include "opt_ipsec.h"
 #include "opt_mac.h"
 #include "opt_mbuf_stress_test.h"
@@ -91,6 +92,12 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, mbuf_
 	&mbuf_frag_size, 0, "Fragment outgoing mbufs to this size");
 #endif
 
+#if defined(IP_NONLOCALBIND)
+static int ip_nonlocalok = 0;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, nonlocalok,
+	CTLFLAG_RW|CTLFLAG_SECURE, &ip_nonlocalok, 0, "");
+#endif
+
 static void	ip_mloopback
 	(struct ifnet *, struct mbuf *, struct sockaddr_in *, int);
 
@@ -856,6 +863,13 @@ ip_ctloutput(struct socket *so, struct s
 			return (error);
 		}
 
+#if defined(IP_NONLOCALBIND)
+		case IP_NONLOCALOK:
+			if (! ip_nonlocalok) {
+			error = ENOPROTOOPT;
+			break;
+		}
+#endif
 		case IP_TOS:
 		case IP_TTL:
 		case IP_MINTTL:
@@ -927,6 +941,11 @@ ip_ctloutput(struct socket *so, struct s
 			case IP_DONTFRAG:
 				OPTSET(INP_DONTFRAG);
 				break;
+#if defined(IP_NONLOCALBIND)
+			case IP_NONLOCALOK:
+				OPTSET(INP_NONLOCALOK);
+				break;
+#endif
 			}
 			break;
 #undef OPTSET



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811182217.mAIMHHjm090641>