diff --git a/sbin/ipfw/Makefile b/sbin/ipfw/Makefile index fd1f05bbe2ef..3effc23dd42e 100644 --- a/sbin/ipfw/Makefile +++ b/sbin/ipfw/Makefile @@ -1,16 +1,5 @@ PROG= ipfw -DPADD= ${LIBKVM} -LDADD= -lkvm MAN8= ipfw.8 -test: ipfw - ./ipfw add reject tcp from any to any - ./ipfw add 11 reject tcp from 1.2.3.4 to 5.6.7.8 established - ./ipfw add 11 reject tcp from 1.2.3.4 to 5.6.7.8/24 in - ./ipfw add 11 reject tcp from 1.2.3.4 to 5.6.7.8 in out - ./ipfw add 11 reject tcp from 1.2.3.4 to 5.6.7.8 frag out - ./ipfw add 11 reject tcp from 1.2.3.4 to 5.6.7.8 tcpf p,f,!a ipopt !ts - ./ipfw add 12 count log udp from 1.2.3.4 to 5.6.7.8 123-125,234,245 - .include diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index 3dc78ec8c8b9..bbf0e4ed3cb1 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -1,25 +1,206 @@ -.Dd November 16, 1994 +.Dd February 24, 1996 .Dt IPFW 8 SMM .Os FreeBSD .Sh NAME .Nm ipfw -.Nd controlling utility for IP firewall / IP accounting facilities. +.Nd controlling utility for IP firewall .Sh SYNOPSIS -.Nm -.Oo -.Fl n -.Oc -.Ar entry_action chain_entry_pattern +.Nm ipfw +.Ar file +.Nm ipfw +flush +.Nm ipfw +zero +.Nm ipfw +delete +.Ar number .Nm ipfw .Oo -.Fl ans +.Fl aN +.Oc +list +.Nm ipfw +add +.Oo +.Ar number +.Oc +.Ar action +.Oo +log +.Oc +.Ar proto +from +.Ar src +to +.Ar dst +.Oo +via +.Ar name|ipno +.Oc +.Oo +.Ar options .Oc -.Ar chain_action chain[s]_type -.\" ipfw [-n] -.\" ipfw [-ans] -.Sh WARNING -This manual page is out of date! .Sh DESCRIPTION +If used as shown in the first synopsis line, the +.Ar file +will be read line by line and applied as arguments to the +.Nm ipfw +command. +.Pp +The ipfw code works by going through the rule-list for each packet, +until a match is found. +All rules have two counters associated with them, a packet count and +a byte count. +These counters are updated when a packet matches the rule. +.Pp +The rules are ordered by a ``line-number'' that is used to order and +delete rules. +If a rule is added without a number, it is put at the end, just before +the terminal ``policy-rule'', and numbered 100 higher than the previous +rule. +.Pp +One rule is always present: +.Bd -literal -offset center +65535 deny all from any to any +.Ed + +this is rule is the default policy, ie. don't allow anything at all. +Your job in setting up rules is to modify this policy to match your +needs. +.Pp +The following options are available: +.Bl -tag -width flag +.It Fl a +While listing, show counter values. This option is the only way to see +accounting records. +.It Fl N +Try to resolve addresses. +.El +.Pp +.Ar action : +.Bl -hang -offset flag -width 1234567890123456 +.It Nm accept +Accept packets that match rule. +The search terminates. +.It Nm pass +same as accept. +.It Nm count +update counters for all packets that match rule. +The search continues with next rule. +.It Nm deny +Discard packets that match this rule. +The search terminates. +.It Nm reject +Discard packets that match this rule, try to send ICMP notice. +The search terminates. +.El +.Pp +When a packet matches a rule with the +.Nm log +keyword, a message will be printed on the console. +.Pp +.Ar proto : +.Bl -hang -offset flag -width 1234567890123456 +.It Nm ip +All packets match. +.It Nm all +All packets match. +.It Nm tcp +Only TCP packets match. +.It Nm udp +Only UDP packets match. +.It Nm icmp +Only ICMP packets match. +.El +.Pp +.Ar src +and +.Ar dst : +.Bl -hang -offset flag -width 1234567890123456 +.It Ar ipno +An ipnumber of the form 1.2.3.4. +Only this exact ip number match the rule. +.It Ar ipno/bits +An ipnumber with a mask width of the form 1.2.3.4/24. +In this case all ip numbers from 1.2.3.0 to 1.2.3.255 will match. +.It Ar ipno:mask +An ipnumber with a mask width of the form 1.2.3.4:255.255.240.0 +In this case all ip numbers from 1.2.0.0 to 1.2.15.255 will match. +.El +.Pp +If ``via'' +.Ar name +is specified, only packets received via or on their way out of an interface +matching +.Ar name +will match this rule. +.Pp +If ``via'' +.Ar ipno +is specified, only packets received via or on their way out of an interface +having the address +.Ar ipno +will match this rule. +.Pp +.Ar options : +.Bl -hang -offset flag -width 1234567890123456 +.It frag +Matches is the packet is a fragment and this is not the first fragment +of the datagram. +.It in +Matches if this packet was on the way in. +.It out +Matches if this packet was on the way out. +.It ipoptions Ar spec +Not yet documented. Look in the source: src/sys/netnet/ipfw.c. +.It established +Matches packets that do not have the SYN bit set. +TCP packets only. +.It setup +Matches packets that have the SYN bit set but no ACK bit. +TCP packets only. +.It tcpflags Ar spec +Not yet documented. Look in the source: src/sys/netnet/ipfw.c. +TCP packets only. +.El +.Sh CHECKLIST +Here are some important points to consider when designing your +rules: +.Bl -bullet -hang -offset flag -width 1234567890123456 +.It +Remember that you filter both packets going in and out. +Most connections needs packets going in both directions. +.It +Remember to test very carefully. +It is a good idea to be near the console when doint this. +.It +Don't forget the loopback interface. +.El +.Sh FINE POINTS +There is one kind of packet that the firewall will always discard, +that is an IP fragment with a fragment offset of one. +This is a valid packet, but it only has one use, to try to circumvent +firewalls. +.Pp +If you are logged in over a network, loading the LKM version of +.Nm +is probably not as straightforward as you would think. +I recommend this command line: +.Bd -literal -offset center +modload /lkm/ipfw_mod.o && \e +ipfw add 32000 allow all from any to any +.Ed + +Along the same lines, doing a +.Bd -literal -offset center +ipfw flush +.Ed + +in similar surroundings is also a bad idea. +.Sh WARNING +This manual page is out of date beyond this point! +It is left here until some new text can be written. +.Sh OLD In the first synopsis form, .Nm controls the firewall and accounting chains. In the second @@ -28,24 +209,6 @@ synopsis form, sets the global firewall / accounting properties and show the chain list's contents. .Pp -The following options are available: -.Bl -tag -width flag -.It Fl a -While listing, show counter values. This option is the only way to see -accounting records. Works only with -.Fl s -.It Fl n -Do not resolve anything. When setting entries, do not try to resolve a -given address. When listing, display addresses in numeric form. -.It Fl s -Short listing form. By default, the listing format is compatible with -.Nm -input string format, so you can save listings to file and then reuse -them. With this option list format is much more short but incompatible -with the -.Nm -syntax. -.El .Pp These are the valid .Ar entry_actions : @@ -323,3 +486,5 @@ The FreeBSD version is written completely by: .Dl Ugen J.S.Antsilevich .Pp while the synopsis is partially compatible with the old one. +.Pp +This has all been extensively rearranged by Poul-Henning Kamp. diff --git a/sbin/ipfw/ipfw.c b/sbin/ipfw/ipfw.c index 010ff184fe96..77c3765b7f0c 100644 --- a/sbin/ipfw/ipfw.c +++ b/sbin/ipfw/ipfw.c @@ -15,36 +15,27 @@ * * NEW command line interface for IP firewall facility * - * $Id: ipfw.c,v 1.19 1996/02/23 15:52:28 phk Exp $ + * $Id: ipfw.c,v 1.20 1996/02/24 00:20:56 phk Exp $ * */ #include #include #include -#include -#include #include -#include -#include -#include +#include +#include #include -#include -#include +#include #include -#include +#include #include -#include -#include +#include #include #include -#define IPFIREWALL -#include - -#define MAXSTR 256 int lineno = -1; -char progname[MAXSTR]; /* Program name for errors */ +char progname[BUFSIZ]; /* Program name for errors */ int s; /* main RAW socket */ int do_resolv=0; /* Would try to resolv all */ @@ -229,6 +220,8 @@ show_ipfw(chain) if (chain->fw_tcpf == IP_FW_TCPF_SYN && chain->fw_tcpnf == IP_FW_TCPF_ACK) + printf(" setup"); + else if (chain->fw_tcpnf == IP_FW_TCPF_SYN && !chain->fw_tcpf) printf(" established"); else if (chain->fw_tcpf || chain->fw_tcpnf) { int _flg_printed = 0; @@ -252,38 +245,23 @@ show_ipfw(chain) printf("\n"); } -struct nlist nlf[]={ { "_ip_fw_chain" } }; - void list(ac, av) int ac; char **av; { - kvm_t *kd; - static char errb[_POSIX2_LINE_MAX]; - struct ip_fw b; - struct ip_fw_chain *fcp,fc; + struct ip_fw *r; + struct ip_fw rules[1024]; + int l,i; - if (!(kd=kvm_openfiles(NULL,NULL,NULL,O_RDONLY,errb))) { - fprintf(stderr,"%s: kvm_openfiles: %s\n", - progname,kvm_geterr(kd)); - exit(1); - } - - if (kvm_nlist(kd,nlf)<0 || nlf[0].n_type==0) { - fprintf(stderr,"%s: kvm_nlist: no namelist in %s\n", - progname,getbootfile()); - exit(1); - } - - kvm_read(kd,(u_long)nlf[0].n_value,&fcp,sizeof fcp); - printf("FireWall chain entries:\n"); - while(fcp!=NULL) { - kvm_read(kd,(u_long)fcp,&fc,sizeof fc); - kvm_read(kd,(u_long)fc.rule,&b,sizeof b); - show_ipfw(&b); - fcp = fc.chain.le_next; - } + memset(rules,0,sizeof rules); + l = sizeof rules; + i = getsockopt(s, IPPROTO_IP, IP_FW_GET, rules, &l); + if (i < 0) + err(2,"getsockopt(IP_FW_GET)"); + printf("FireWall chain entries: %d %d\n",l,i); + for (r=rules; l >= sizeof rules[0]; r++, l-=sizeof rules[0]) + show_ipfw(r); } void @@ -513,9 +491,6 @@ add(ac,av) rule.fw_flg |= IP_FW_F_PRN; av++; ac--; } - /* [protocol] */ - if (ac && !strncmp(*av,"protocol",strlen(*av))) { av++; ac--; } - /* protocol */ if (ac && !strncmp(*av,"ip",strlen(*av))) { rule.fw_flg |= IP_FW_F_ALL; av++; ac--; @@ -557,6 +532,23 @@ add(ac,av) av++; ac--; } + if (ac && !strncmp(*av,"via",strlen(*av))) { + av++; ac--; + if (!isdigit(**av)) { + char *q; + + strcpy(rule.fw_via_name, *av); + for (q = rule.fw_via_name; *q && !isdigit(*q); q++) + continue; + rule.fw_via_unit = atoi(q); + *q = '\0'; + rule.fw_flg |= IP_FW_F_IFNAME; + } else if (inet_aton(*av,&rule.fw_via_ip) == INADDR_NONE) { + show_usage("bad IP# after via\n"); + } + av++; ac--; + } + while (ac) { if (!strncmp(*av,"frag",strlen(*av))) { rule.fw_flg |= IP_FW_F_FRAG; av++; ac--; continue; @@ -567,21 +559,27 @@ add(ac,av) if (!strncmp(*av,"out",strlen(*av))) { rule.fw_flg |= IP_FW_F_OUT; av++; ac--; continue; } - if (!strncmp(*av,"established",strlen(*av))) { - rule.fw_tcpf |= IP_FW_TCPF_SYN; - rule.fw_tcpnf |= IP_FW_TCPF_ACK; - av++; ac--; continue; - } - if (ac > 1 && !strncmp(*av,"tcpflags",strlen(*av))) { - av++; ac--; - fill_tcpflag(&rule.fw_tcpf, &rule.fw_tcpnf, av); - av++; ac--; continue; - } if (ac > 1 && !strncmp(*av,"ipoptions",strlen(*av))) { av++; ac--; fill_ipopt(&rule.fw_ipopt, &rule.fw_ipnopt, av); av++; ac--; continue; } + if ((rule.fw_flg & IP_FW_F_KIND) == IP_FW_F_TCP) { + if (!strncmp(*av,"established",strlen(*av))) { + rule.fw_tcpnf |= IP_FW_TCPF_SYN; + av++; ac--; continue; + } + if (!strncmp(*av,"setup",strlen(*av))) { + rule.fw_tcpf |= IP_FW_TCPF_SYN; + rule.fw_tcpnf |= IP_FW_TCPF_ACK; + av++; ac--; continue; + } + if (ac > 1 && !strncmp(*av,"tcpflags",strlen(*av))) { + av++; ac--; + fill_tcpflag(&rule.fw_tcpf, &rule.fw_tcpnf, av); + av++; ac--; continue; + } + } printf("%d %s\n",ac,*av); show_usage("Unknown argument\n"); } @@ -606,12 +604,12 @@ ipfw_main(ac,av) show_usage(NULL); } - while ((ch = getopt(ac, av ,"an")) != EOF) + while ((ch = getopt(ac, av ,"aN")) != EOF) switch(ch) { case 'a': do_acct=1; break; - case 'n': + case 'N': do_resolv=1; break; case '?': @@ -656,7 +654,7 @@ main(ac, av) char **av; { #define MAX_ARGS 32 - char buf[_POSIX_ARG_MAX]; + char buf[BUFSIZ]; char *args[MAX_ARGS]; char linename[10]; int i; @@ -676,7 +674,7 @@ main(ac, av) if (av[1] && !access(av[1], R_OK)) { lineno = 0; f = fopen(av[1], "r"); - while (fgets(buf, _POSIX_ARG_MAX, f)) { + while (fgets(buf, BUFSIZ, f)) { if (buf[strlen(buf)-1]=='\n') buf[strlen(buf)-1] = 0;