From owner-freebsd-ipfw@FreeBSD.ORG Mon Sep 22 16:07:50 2003 Return-Path: Delivered-To: freebsd-ipfw@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 793CA16A4B3 for ; Mon, 22 Sep 2003 16:07:50 -0700 (PDT) Received: from xorpc.icir.org (xorpc.icir.org [192.150.187.68]) by mx1.FreeBSD.org (Postfix) with ESMTP id DBED843FE1 for ; Mon, 22 Sep 2003 16:07:49 -0700 (PDT) (envelope-from rizzo@xorpc.icir.org) Received: from xorpc.icir.org (localhost [127.0.0.1]) by xorpc.icir.org (8.12.9p1/8.12.3) with ESMTP id h8MN7isd061911; Mon, 22 Sep 2003 16:07:44 -0700 (PDT) (envelope-from rizzo@xorpc.icir.org) Received: (from rizzo@localhost) by xorpc.icir.org (8.12.9p1/8.12.3/Submit) id h8MN7id6061910; Mon, 22 Sep 2003 16:07:44 -0700 (PDT) (envelope-from rizzo) Date: Mon, 22 Sep 2003 16:07:44 -0700 From: Luigi Rizzo To: ipfw@freebsd.org Message-ID: <20030922160744.A61711@xorpc.icir.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5.1i Subject: [PATCH FOR REVIEW] layer2 ipfw 'fwd' support X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 22 Sep 2003 23:07:50 -0000 hi, for those interested in using ipfw 'fwd' instructions in a bridge (e.g. to create a transparent proxy with a bridge) here is a patch to try for ip_fw2.c (and a trivial one-line change in ip_input.c) The change to ip_input.c matches more closely what the comment says: if the packet is tagged by the firewall as 'PACKET_TAG_IPFORWARD' than you skip the pass through the firewall, but still check to see where the packet goes. The ip_fw2.c change does the following: when the bridge detects a layer2 packet, it passes it to ip_input() [!!!layering violation!!!] with a proper tag so that the packet is subject to the same processing it would have in a router. [BTW i believe the same approach could be used to implement 'divert' within a bridge if we only care for IP packets -- i.e. we tag the packet and pass it to the upper layer] The usual restrictions apply -- if you 'forward' to another box then it must be on the same subnet as one of the interfaces of the middlebox, because IP addresses are unchanged. Also, despite the fact you are doing the forwarding on a bridge, if the packet must go out you need to set net.inet.ip.forwarding=1 because the forwarding is done at layer 3. ------------------------------- So, QUICK USAGE INSTRUCTIONS: sample topology: rl0 rl1 [clients]------[bridge]--+----[rest of the world]] | +----[proxy] on clients: no configuration necessary, as the proxy is transparent! on bridge: sysctl net.link.ether.bridge_cfg="rl0 rl1" sysctl net.link.ether.bridge_ipfw=1 sysctl net.link.ether.bridge=1 sysctl net.inet.ip.forwarding=1 ipfw add forward proxy proto tcp from any to any 80 on proxy: ipfw add forward localhost,8080 tcp from not me to any 80 ------------------------------- cheers luigi Index: ip_fw2.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v retrieving revision 1.6.2.16 diff -u -r1.6.2.16 ip_fw2.c --- ip_fw2.c 17 Jul 2003 06:03:39 -0000 1.6.2.16 +++ ip_fw2.c 22 Sep 2003 22:21:38 -0000 @@ -1977,12 +2022,33 @@ goto done; case O_FORWARD_IP: +#if 0 if (args->eh) /* not valid on layer2 pkts */ break; +#endif if (!q || dyn_dir == MATCH_FORWARD) args->next_hop = &((ipfw_insn_sa *)cmd)->sa; retval = 0; + if (args->eh) { + struct m_hdr tag; + + if (hlen == 0) /* non IP */ + break; + /* + * tag with PACKET_TAG_IPFORWARD + * call ip_input() (need ip_forwarding=1 + * if this has to go out) + * mark packet as comsumed by the firewall + */ + tag.mh_type = MT_TAG; + tag.mh_flags = PACKET_TAG_IPFORWARD; + tag.mh_data = (caddr_t)args->next_hop; + tag.mh_next = m; + args->m = NULL; + retval = IP_FW_PORT_DENY_FLAG; + ip_input((struct mbuf *)&tag); + } goto done; default: Index: ip_input.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v retrieving revision 1.130.2.53 diff -u -r1.130.2.53 ip_input.c --- ip_input.c 23 Jun 2003 17:53:50 -0000 1.130.2.53 +++ ip_input.c 22 Sep 2003 22:23:23 -0000 @@ -462,7 +462,7 @@ * skip the firewall a second time */ if (args.next_hop) - goto ours; + goto pass; /* XXX was 'ours' */ args.m = m; i = ip_fw_chk_ptr(&args);