svn commit: r185067 - in user/adrian/spoof_bind: sbin/ipfw
share/man/man4 sys/conf sys/net sys/netinet
Adrian Chadd
adrian at FreeBSD.org
Tue Nov 18 14:17:18 PST 2008
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
More information about the svn-src-user
mailing list