Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Jan 2008 14:14:53 GMT
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 132707 for review
Message-ID:  <200801071414.m07EErYt035913@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=132707

Change 132707 by adrian@wendy on 2008/01/07 14:14:51

	Bring over most of the initial work that Julian emailed me a while
	ago. (Thanks Julian.)
	
	This hasn't been compiled or tested yet!

Affected files ...

.. //depot/projects/adrian_spoof_clientip/src/sbin/ipfw/ipfw2.c#2 edit
.. //depot/projects/adrian_spoof_clientip/src/sys/conf/NOTES#2 edit
.. //depot/projects/adrian_spoof_clientip/src/sys/conf/options#2 edit
.. //depot/projects/adrian_spoof_clientip/src/sys/net/if_bridge.c#2 edit
.. //depot/projects/adrian_spoof_clientip/src/sys/netinet/in.h#2 edit
.. //depot/projects/adrian_spoof_clientip/src/sys/netinet/in_pcb.c#2 edit
.. //depot/projects/adrian_spoof_clientip/src/sys/netinet/in_pcb.h#2 edit
.. //depot/projects/adrian_spoof_clientip/src/sys/netinet/ip_fw.h#2 edit
.. //depot/projects/adrian_spoof_clientip/src/sys/netinet/ip_fw2.c#2 edit
.. //depot/projects/adrian_spoof_clientip/src/sys/netinet/ip_output.c#2 edit

Differences ...

==== //depot/projects/adrian_spoof_clientip/src/sbin/ipfw/ipfw2.c#2 (text+ko) ====

@@ -298,6 +298,7 @@
 	TOK_ANTISPOOF,
 	TOK_IPSEC,
 	TOK_COMMENT,
+	TOK_FOR_ME,
 
 	TOK_PLR,
 	TOK_NOERROR,
@@ -426,6 +427,7 @@
 	{ "uid",		TOK_UID },
 	{ "gid",		TOK_GID },
 	{ "jail",		TOK_JAIL },
+	{ "for-me",		TOK_FOR_ME },
 	{ "in",			TOK_IN },
 	{ "limit",		TOK_LIMIT },
 	{ "keep-state",		TOK_KEEPSTATE },
@@ -2026,6 +2028,10 @@
 					    O_TAGGED);
 				break;
 
+			case O_FOR_ME:
+				printf(" for-me");
+				break;
+
 			default:
 				printf(" [opcode %d len %d]",
 				    cmd->opcode, cmd->len);
@@ -5612,6 +5618,10 @@
 			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);
 		}

==== //depot/projects/adrian_spoof_clientip/src/sys/conf/NOTES#2 (text+ko) ====

@@ -614,6 +614,14 @@
 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

==== //depot/projects/adrian_spoof_clientip/src/sys/conf/options#2 (text+ko) ====

@@ -363,6 +363,7 @@
 INET6			opt_inet6.h
 IPSEC			opt_ipsec.h
 IPSEC_DEBUG		opt_ipsec.h
+IP_NONLOCALBIND		opt_inet.h
 IPSEC_FILTERTUNNEL	opt_ipsec.h
 IPDIVERT
 DUMMYNET		opt_ipdn.h

==== //depot/projects/adrian_spoof_clientip/src/sys/net/if_bridge.c#2 (text+ko) ====

@@ -2897,6 +2897,10 @@
 	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 */
@@ -2956,6 +2960,7 @@
 #ifdef INET6
 		case ETHERTYPE_IPV6:
 #endif /* INET6 */
+			is_ip = 1;
 			break;
 		default:
 			/*
@@ -3014,6 +3019,25 @@
 		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 */

==== //depot/projects/adrian_spoof_clientip/src/sys/netinet/in.h#2 (text+ko) ====

@@ -435,6 +435,7 @@
 #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 */

==== //depot/projects/adrian_spoof_clientip/src/sys/netinet/in_pcb.c#2 (text+ko) ====

@@ -35,6 +35,7 @@
 __FBSDID("$FreeBSD: src/sys/netinet/in_pcb.c,v 1.198 2007/12/22 10:06:11 rwatson Exp $");
 
 #include "opt_ddb.h"
+#include "opt_inet.h"
 #include "opt_ipsec.h"
 #include "opt_inet6.h"
 #include "opt_mac.h"
@@ -323,7 +324,11 @@
 		} 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;

==== //depot/projects/adrian_spoof_clientip/src/sys/netinet/in_pcb.h#2 (text+ko) ====

@@ -310,6 +310,8 @@
 #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 */
 

==== //depot/projects/adrian_spoof_clientip/src/sys/netinet/ip_fw.h#2 (text+ko) ====

@@ -160,6 +160,7 @@
 
 	O_TAG,   		/* arg1=tag number */
 	O_TAGGED,		/* arg1=tag number */
+	O_FOR_ME,		/* check for a PCB here for this packet */
 
 	O_LAST_OPCODE		/* not an opcode!		*/
 };

==== //depot/projects/adrian_spoof_clientip/src/sys/netinet/ip_fw2.c#2 (text+ko) ====

@@ -2237,6 +2237,46 @@
 #endif
 
 /*
+ * 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
@@ -2259,6 +2299,7 @@
  *	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:
  *
@@ -2769,6 +2810,24 @@
 						    &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);
@@ -3449,8 +3508,11 @@
 			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,
@@ -4107,6 +4169,7 @@
 		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:

==== //depot/projects/adrian_spoof_clientip/src/sys/netinet/ip_output.c#2 (text+ko) ====

@@ -33,6 +33,7 @@
 __FBSDID("$FreeBSD: src/sys/netinet/ip_output.c,v 1.277 2007/10/24 19:03:59 rwatson Exp $");
 
 #include "opt_ipfw.h"
+#include "opt_inet.h"
 #include "opt_ipsec.h"
 #include "opt_mac.h"
 #include "opt_mbuf_stress_test.h"
@@ -84,6 +85,12 @@
 	&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);
 
@@ -839,6 +846,13 @@
 			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:
@@ -910,6 +924,11 @@
 			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?200801071414.m07EErYt035913>