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>