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>