From owner-freebsd-ipfw Thu Oct 3 16:28: 9 2002 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 4BFC137B404 for ; Thu, 3 Oct 2002 16:28:05 -0700 (PDT) Received: from mta11.srv.hcvlny.cv.net (mta11.srv.hcvlny.cv.net [167.206.5.46]) by mx1.FreeBSD.org (Postfix) with ESMTP id 631AF43E6E for ; Thu, 3 Oct 2002 16:28:03 -0700 (PDT) (envelope-from avg@icyb.net.ua) Received: from conversion-daemon.mta11.srv.hcvlny.cv.net by mta11.srv.hcvlny.cv.net (iPlanet Messaging Server 5.2 HotFix 0.9 (built Jul 29 2002)) id <0H3F00B01G7WMH@mta11.srv.hcvlny.cv.net> for freebsd-ipfw@freebsd.org; Thu, 03 Oct 2002 18:43:39 -0400 (EDT) Received: from edge.foundation.invalid (ool-182f90f3.dyn.optonline.net [24.47.144.243]) by mta11.srv.hcvlny.cv.net (iPlanet Messaging Server 5.2 HotFix 0.9 (built Jul 29 2002)) with ESMTP id <0H3F00J2IF3ZV6@mta11.srv.hcvlny.cv.net>; Thu, 03 Oct 2002 18:14:24 -0400 (EDT) Date: Thu, 03 Oct 2002 18:14:23 -0400 (EDT) From: Andriy Gapon Subject: Re: Natd plus statefull connections impossible? X-X-Sender: avg@edge.foundation.invalid To: Georg Graf Cc: freebsd-ipfw@freebsd.org Message-id: <20021003161757.I32181-100000@edge.foundation.invalid> MIME-version: 1.0 Content-type: TEXT/PLAIN; charset=US-ASCII Content-transfer-encoding: 7BIT Sender: owner-freebsd-ipfw@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Georg, I've been trying to do the same thing (or almost the same) recently and I have found this one trick on some mailing list archive (don't remember where and who is the author, try searching on google for "nat ipfw stateful"). After playing around for some time I have some observations/rules of thumb that helped me to build a quite simple and much stateless set of rules than I originally had in my mind. 1simpe/ no stateful rules before divert rules 1expanded/ if you have stateful rules that may match the same packet that you want to go throgh natd, you must not put any keep-state, check-state rules before divert 2/ most of the rules will be after divert(s), so always keep in mind that all incoming traffic has addresses internal_ip<-real_world_ip and all outgoing traffic has addresses external_interface_ip->real_world_ip. 3/ dynamic rules that were created by match of a stateful rule on a particular interface do apply to all interfaces 4/ the only way to have a dynamic rule that matches internal_ip<-real_world_ip packet is to put a keep-state rule on interal interface that would match internal_ip->real_world_ip packet when it enters a gateway host 5/ for access to a server on the internal network you can have either of: a. rule that allows packets from XXX to internal adderss:port b. (trust natd) rule that allows all packets after divert that originated in real world and go to internal network plus either of: a'. rule that allows packets from external_if:forwarded_port to XXX b'. general rule that allows all outgoing traffic from external_if Ok, here is my simplest firewall ruleset: (rl1 - internal_if, rl0 - external_if) #loopback stuff add 00100 allow ip from any to any via lo0 add 00110 deny ip from any to 127.0.0.0/8 add 00120 deny ip from 127.0.0.0/8 to any #trust internal network add 00125 allow all from any to any via rl1 #make sure we don't leak internal traffic out there add 00150 deny all from any to 192.168.0.0/16 via rl0 add 00200 divert natd all from 192.168.0.0/16 to any out via rl0 #probably just paranoia add 00250 deny all from 192.168.0.0/16 to any via rl0 #allow me to connect to gateway from outside via ssh (can not be stateful) add 00400 allow tcp from any to me ssh in via rl0 add 00410 allow tcp from me ssh to any out via rl0 #translate incoming add 00500 divert natd all from any to me in via rl0 #trust natd, it shouldn't translate destination address to my internal #network unless session was initiated from there, or this a port, address #etc forwarding add 00510 allow ip from any to 192.168.0.0/16 in via rl0 #check dynamic rules add 00600 check-state #allow all outgoing traffic (this will match packets both originated in #in internal network and here on gateway add 01000 allow ip from me to any out via rl0 keep-state add 01200 allow icmp from any to any #all legitimate traffic should have matched above add 01300 deny log logamount 30 tcp from any to any established #don't put this garbage in logs add 64900 deny udp from any to any 137,138,139 in recv rl0 add 64901 deny tcp from any to any 137,138,139,443,1443,27374 in recv rl0 add 65000 deny log logamount 30 ip from any to any as you have figured out this allows all traffic established from inside as well as traffic established from the outside and forwarded ny natd. Here's also much more elaborate, prohibitive and paranoid ruleset. It also illustrates the idea of keep-state rules on internal interface that produce dynamic rules for the external interface: (sorry, much less comments) add 00100 allow ip from any to any via lo0 add 00110 deny ip from any to 127.0.0.0/8 add 00120 deny ip from 127.0.0.0/8 to any add 00130 allow udp from any bootps to any bootpc add 00131 allow udp from me bootpc to any bootps add 00150 deny all from any to 10.0.0.0/8 via rl0 add 00151 deny all from any to 172.16.0.0/12 via rl0 add 00152 deny all from any to 192.168.0.0/16 via rl0 add 00153 deny all from any to 0.0.0.0/8 via rl0 add 00154 deny all from any to 169.254.0.0/16 via rl0 add 00155 deny all from any to 192.0.2.0/24 via rl0 add 00156 deny all from any to 224.0.0.0/4 via rl0 add 00157 deny all from any to 240.0.0.0/4 via rl0 add 00200 divert natd all from 192.168.0.0/16 to any out via rl0 add 00250 deny all from 10.0.0.0/8 to any via rl0 add 00251 deny all from 172.16.0.0/12 to any via rl0 add 00252 deny all from 192.168.0.0/16 to any via rl0 add 00253 deny all from 0.0.0.0/8 to any via rl0 add 00254 deny all from 169.254.0.0/16 to any via rl0 add 00255 deny all from 192.0.2.0/24 to any via rl0 add 00256 deny all from 224.0.0.0/4 to any via rl0 add 00257 deny all from 240.0.0.0/4 to any via rl0 add 00301 deny ip from not 192.168.1.0/24 to any in via rl1 add 00303 deny ip from any to not 192.168.1.0/24 out via rl1 add 00400 allow tcp from any to me ssh in via rl0 add 00410 allow tcp from me ssh to any out via rl0 add 00500 divert natd all from any to me in via rl0 #keep-state rules on the internal if add 00550 allow tcp from any to not 192.168.0.0/16 in via rl1 setup keep-state add 00552 allow ip from any to not 192.168.0.0/16 in via rl1 keep-state add 00553 allow all from any to any via rl1 add 00600 deny log logamount 10 ip from any to any frag add 00900 reset log logamount 10 tcp from any to me auth in via rl0 #allow only ssh on 2222, and 49333 port connection #to a particular internal host add 00950 allow tcp from any to 192.168.1.12 22 in via rl0 setup add 00951 allow tcp from me 2222 to any out via rl0 established add 00970 allow tcp from any to 192.168.1.12 49333 in via rl0 setup add 00971 allow tcp from me 49333 to any out via rl0 established add 01000 deny log logamount 30 tcp from any to any established add 01002 allow tcp from me to any out via rl0 setup keep-state add 01103 allow udp from me to any domain via rl0 keep-state add 01104 allow tcp from me to any domain via rl0 setup keep-state add 01105 allow udp from me to any ntp via rl0 keep-state add 01106 allow udp from me to any out via rl0 add 01200 allow icmp from any to any add 64000 allow tcp from me to any out tcpflags rst add 64900 deny udp from any to any 137,138,139 in recv rl0 add 64901 deny tcp from any to any 137,138,139,443,1443,27374 in recv rl0 add 65000 deny log logamount 30 ip from any to any comments are welcome. Hope this is useful for you, because both configs are actually working for me. -- Andriy Gapon * Hang on tightly, let go lightly. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ipfw" in the body of the message