PERFORCE change 132707 for review
Adrian Chadd
adrian at FreeBSD.org
Mon Jan 7 06:14:54 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=132707
Change 132707 by adrian at 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
More information about the p4-projects
mailing list