Completely rewrite handling of protocol field for firewalls, things are
now completely consistent across all IP protocols and should be quite a bit faster. Use getprotoname() extensively, performed minor cleanups of admin utility. The admin utility could use a good kick in the pants. Basicly, these were the minimal changes I could make to the code to get it up to tollerable shape. There will be some future commits to clean up the basic architecture of the firewall code, and if I'm feeling ambitious, I may pull in changes like NAT from Linux and make the firewall hooks comletely generic so that a user can either load the ipfw module or the ipfilter module (cf Darren Reed). Discussed with: fenner & alex
This commit is contained in:
parent
1ec21d5930
commit
978eb210d1
@ -5,7 +5,7 @@
|
||||
.Nm ipfw
|
||||
.Nd controlling utility for IP firewall
|
||||
.Sh SYNOPSIS
|
||||
.Nm ipfw
|
||||
.Nm
|
||||
.Ar file
|
||||
.Nm ipfw
|
||||
flush
|
||||
@ -47,10 +47,12 @@ via
|
||||
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
|
||||
.Nm
|
||||
command.
|
||||
.Pp
|
||||
The ipfw code works by going through the rule-list for each packet,
|
||||
The
|
||||
.Nm
|
||||
code works by going through the rule-list for each packet,
|
||||
until a match is found.
|
||||
All rules have two associated counters, a packet count and
|
||||
a byte count.
|
||||
@ -142,6 +144,10 @@ Only TCP packets match.
|
||||
Only UDP packets match.
|
||||
.It Nm icmp
|
||||
Only ICMP packets match.
|
||||
.It Nm <number|name>
|
||||
Only packets for the specified protocol matches (see
|
||||
.Pa /etc/protocols
|
||||
for a complete list).
|
||||
.El
|
||||
.Pp
|
||||
.Ar src
|
||||
@ -249,14 +255,6 @@ Matches if the ICMP type is in the list
|
||||
.Ar types .
|
||||
The list may be specified as any combination of ranges
|
||||
or individual types separated by commas.
|
||||
.It proto Ar ipproto
|
||||
Matches if the protocol field in the IP header matches
|
||||
any of the protocol numbers specified by the list
|
||||
.Ar ipproto
|
||||
(see
|
||||
.Pa /etc/protocols
|
||||
for a complete list).
|
||||
Protocol ranges may not be used.
|
||||
.El
|
||||
.Sh CHECKLIST
|
||||
Here are some important points to consider when designing your
|
||||
@ -324,8 +322,6 @@ This rule diverts all incoming packets from 192.168.2.0/24 to divert port 5000:
|
||||
.Pp
|
||||
.Dl ipfw divert 5000 all from 192.168.2.0/24 to any in
|
||||
.Sh SEE ALSO
|
||||
.Xr gethostbyname 3 ,
|
||||
.Xr getservbyport 3 ,
|
||||
.Xr divert 4 ,
|
||||
.Xr ip 4 ,
|
||||
.Xr ipfirewall 4 ,
|
||||
@ -345,16 +341,12 @@ do anything you don't understand.
|
||||
.Pp
|
||||
When manipulating/adding chain entries, service and protocol names are
|
||||
not accepted.
|
||||
.Sh AUTHORS
|
||||
Ugen J. S. Antsilevich,
|
||||
Poul-Henning Kamp,
|
||||
Alex Nash,
|
||||
Archie Cobbs.
|
||||
API based upon code written by Daniel Boulet for BSDI.
|
||||
.Sh HISTORY
|
||||
Initially this utility was written for BSDI by:
|
||||
.Pp
|
||||
.Dl Daniel Boulet <danny@BouletFermat.ab.ca>
|
||||
.Pp
|
||||
The FreeBSD version is written completely by:
|
||||
.Pp
|
||||
.Dl Ugen J.S.Antsilevich <ugen@FreeBSD.ORG>
|
||||
.Pp
|
||||
This has all been extensively rearranged by Poul-Henning Kamp and
|
||||
Alex Nash.
|
||||
.Pp
|
||||
Packet diversion added by Archie Cobbs <archie@whistle.com>.
|
||||
.Nm
|
||||
first appeared in FreeBSD 2.0.
|
||||
|
160
sbin/ipfw/ipfw.c
160
sbin/ipfw/ipfw.c
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 1996 Alex Nash
|
||||
* Copyright (c) 1996 Poul-Henning Kamp
|
||||
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
|
||||
* Copyright (c) 1994 Ugen J.S.Antsilevich
|
||||
*
|
||||
* Idea and grammar partially left from:
|
||||
* Copyright (c) 1993 Daniel Boulet
|
||||
*
|
||||
@ -16,7 +16,7 @@
|
||||
*
|
||||
* NEW command line interface for IP firewall facility
|
||||
*
|
||||
* $Id: ipfw.c,v 1.30 1996/08/05 02:38:51 alex Exp $
|
||||
* $Id: ipfw.c,v 1.31 1996/08/13 00:41:05 pst Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -66,43 +66,27 @@ mask_bits(m_ad)
|
||||
}
|
||||
|
||||
void
|
||||
print_port(port, comma, flg)
|
||||
u_short port,flg;
|
||||
print_port(prot, port, comma)
|
||||
u_char prot;
|
||||
u_short port;
|
||||
const char *comma;
|
||||
{
|
||||
struct servent *se;
|
||||
struct protoent *pe;
|
||||
const char *protocol;
|
||||
int printed = 0;
|
||||
|
||||
if (do_resolv) {
|
||||
struct servent *se;
|
||||
struct protoent *pe;
|
||||
const char *protocol;
|
||||
pe = getprotobynumber(prot);
|
||||
if (pe)
|
||||
protocol = pe->p_name;
|
||||
else
|
||||
protocol = NULL;
|
||||
|
||||
switch (flg & IP_FW_F_KIND) {
|
||||
case IP_FW_F_TCP:
|
||||
protocol = "tcp";
|
||||
break;
|
||||
case IP_FW_F_UDP:
|
||||
protocol = "udp";
|
||||
break;
|
||||
default:
|
||||
protocol = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (protocol) {
|
||||
se = getservbyport(htons(port), protocol);
|
||||
|
||||
if (se) {
|
||||
printf("%s%s", comma, se->s_name);
|
||||
printed = 1;
|
||||
}
|
||||
} else {
|
||||
pe = getprotobynumber(port);
|
||||
|
||||
if (pe) {
|
||||
printf("%s%s", comma, pe->p_name);
|
||||
printed = 1;
|
||||
}
|
||||
se = getservbyport(htons(port), protocol);
|
||||
if (se) {
|
||||
printf("%s%s", comma, se->s_name);
|
||||
printed = 1;
|
||||
}
|
||||
}
|
||||
if (!printed)
|
||||
@ -116,7 +100,8 @@ show_ipfw(chain)
|
||||
char *comma;
|
||||
u_long adrt;
|
||||
struct hostent *he;
|
||||
int i,mb;
|
||||
struct protoent *pe;
|
||||
int i, mb;
|
||||
|
||||
if (do_resolv)
|
||||
setservent(1/*stayopen*/);
|
||||
@ -164,24 +149,13 @@ show_ipfw(chain)
|
||||
if (chain->fw_flg & IP_FW_F_PRN)
|
||||
printf(" log");
|
||||
|
||||
switch (chain->fw_flg & IP_FW_F_KIND) {
|
||||
case IP_FW_F_ICMP:
|
||||
printf(" icmp ");
|
||||
break;
|
||||
case IP_FW_F_TCP:
|
||||
printf(" tcp ");
|
||||
break;
|
||||
case IP_FW_F_UDP:
|
||||
printf(" udp ");
|
||||
break;
|
||||
case IP_FW_F_ALL:
|
||||
printf(" ip ");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pe = getprotobynumber(chain->fw_prot);
|
||||
if (pe)
|
||||
printf(" %s", pe->p_name);
|
||||
else
|
||||
printf("%u", chain->fw_prot);
|
||||
|
||||
printf("from ");
|
||||
printf(" from ");
|
||||
|
||||
adrt=ntohl(chain->fw_smsk.s_addr);
|
||||
if (adrt==ULONG_MAX && do_resolv) {
|
||||
@ -210,10 +184,10 @@ show_ipfw(chain)
|
||||
printf(inet_ntoa(chain->fw_src));
|
||||
}
|
||||
|
||||
if ((chain->fw_flg & IP_FW_F_KIND) != IP_FW_F_ALL) {
|
||||
if (chain->fw_prot != IPPROTO_IP) {
|
||||
comma = " ";
|
||||
for (i=0;i<chain->fw_nsp; i++ ) {
|
||||
print_port(chain->fw_pts[i], comma, chain->fw_flg);
|
||||
print_port(chain->fw_prot, chain->fw_pts[i], comma);
|
||||
if (i==0 && (chain->fw_flg & IP_FW_F_SRNG))
|
||||
comma = "-";
|
||||
else
|
||||
@ -252,25 +226,14 @@ show_ipfw(chain)
|
||||
|
||||
comma = " ";
|
||||
for (i=0;i<chain->fw_ndp;i++) {
|
||||
print_port(chain->fw_pts[chain->fw_nsp+i], comma, chain->fw_flg);
|
||||
print_port(chain->fw_prot, chain->fw_pts[chain->fw_nsp+i],
|
||||
comma);
|
||||
if (i==0 && (chain->fw_flg & IP_FW_F_DRNG))
|
||||
comma = "-";
|
||||
else
|
||||
comma = ",";
|
||||
}
|
||||
|
||||
if ((chain->fw_flg & IP_FW_F_KIND) == IP_FW_F_ALL && chain->fw_nsp) {
|
||||
printf(" proto");
|
||||
comma = " ";
|
||||
for (i=0;i<chain->fw_nsp; i++) {
|
||||
print_port(chain->fw_pts[i], comma, chain->fw_flg);
|
||||
if (i==0 && (chain->fw_flg & IP_FW_F_SRNG))
|
||||
comma = "-";
|
||||
else
|
||||
comma = ",";
|
||||
}
|
||||
}
|
||||
|
||||
if ((chain->fw_flg & IP_FW_F_IN) && (chain->fw_flg & IP_FW_F_OUT))
|
||||
;
|
||||
else if (chain->fw_flg & IP_FW_F_IN)
|
||||
@ -387,7 +350,7 @@ show_usage(str)
|
||||
"\t\tzero [number]\n"
|
||||
"\trule:\taction proto src dst extras...\n"
|
||||
"\t\taction: {allow|deny|reject|count|divert port} [log]\n"
|
||||
"\t\tproto: {ip|tcp|udp|icmp}}\n"
|
||||
"\t\tproto: {ip|tcp|udp|icmp|<number>}}\n"
|
||||
"\t\tsrc: from {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n"
|
||||
"\t\tdst: to {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n"
|
||||
"\textras:\n"
|
||||
@ -470,22 +433,17 @@ fill_ip(ipno, mask, acp, avp)
|
||||
}
|
||||
|
||||
void
|
||||
add_port(cnt, ptr, off, port, proto)
|
||||
add_port(cnt, ptr, off, port)
|
||||
u_short *cnt, *ptr, off, port;
|
||||
int proto;
|
||||
{
|
||||
if (proto && port > 255)
|
||||
errx(1, "proto must be in the range 0-255");
|
||||
if (off + *cnt >= IP_FW_MAX_PORTS)
|
||||
errx(1, "too many %s (max is %d)",
|
||||
proto ? "protocols" : "ports",
|
||||
IP_FW_MAX_PORTS);
|
||||
errx(1, "too many ports (max is %d)", IP_FW_MAX_PORTS);
|
||||
ptr[off+*cnt] = port;
|
||||
(*cnt)++;
|
||||
}
|
||||
|
||||
int
|
||||
fill_port(cnt, ptr, off, arg, proto)
|
||||
fill_port(cnt, ptr, off, arg)
|
||||
u_short *cnt, *ptr, off;
|
||||
char *arg;
|
||||
{
|
||||
@ -494,17 +452,15 @@ fill_port(cnt, ptr, off, arg, proto)
|
||||
|
||||
s = strchr(arg,'-');
|
||||
if (s) {
|
||||
if (proto)
|
||||
errx(1,"proto ranges are not allowed");
|
||||
*s++ = '\0';
|
||||
if (strchr(arg, ','))
|
||||
errx(1, "port range must be first in list");
|
||||
add_port(cnt, ptr, off, *arg ? atoi(arg) : 0x0000, proto);
|
||||
add_port(cnt, ptr, off, *arg ? atoi(arg) : 0x0000);
|
||||
arg = s;
|
||||
s = strchr(arg,',');
|
||||
if (s)
|
||||
*s++ = '\0';
|
||||
add_port(cnt, ptr, off, *arg ? atoi(arg) : 0xffff, proto);
|
||||
add_port(cnt, ptr, off, *arg ? atoi(arg) : 0xffff);
|
||||
arg = s;
|
||||
initial_range = 1;
|
||||
}
|
||||
@ -512,7 +468,7 @@ fill_port(cnt, ptr, off, arg, proto)
|
||||
s = strchr(arg,',');
|
||||
if (s)
|
||||
*s++ = '\0';
|
||||
add_port(cnt, ptr, off, atoi(arg), proto);
|
||||
add_port(cnt, ptr, off, atoi(arg));
|
||||
arg = s;
|
||||
}
|
||||
return initial_range;
|
||||
@ -644,6 +600,8 @@ add(ac,av)
|
||||
{
|
||||
struct ip_fw rule;
|
||||
int i;
|
||||
u_char proto;
|
||||
struct protoent *pe;
|
||||
|
||||
memset(&rule, 0, sizeof rule);
|
||||
|
||||
@ -683,19 +641,18 @@ add(ac,av)
|
||||
}
|
||||
|
||||
/* protocol */
|
||||
if (ac && !strncmp(*av,"ip",strlen(*av))) {
|
||||
rule.fw_flg |= IP_FW_F_ALL; av++; ac--;
|
||||
} else if (ac && !strncmp(*av,"all",strlen(*av))) {
|
||||
rule.fw_flg |= IP_FW_F_ALL; av++; ac--;
|
||||
} else if (ac && !strncmp(*av,"tcp",strlen(*av))) {
|
||||
rule.fw_flg |= IP_FW_F_TCP; av++; ac--;
|
||||
} else if (ac && !strncmp(*av,"udp",strlen(*av))) {
|
||||
rule.fw_flg |= IP_FW_F_UDP; av++; ac--;
|
||||
} else if (ac && !strncmp(*av,"icmp",strlen(*av))) {
|
||||
rule.fw_flg |= IP_FW_F_ICMP; av++; ac--;
|
||||
} else {
|
||||
if (ac) {
|
||||
if ((proto = atoi(*av)) > 0) {
|
||||
rule.fw_prot = proto; av++; ac--;
|
||||
} else if (!strncmp(*av,"all",strlen(*av))) {
|
||||
rule.fw_prot = IPPROTO_IP; av++; ac--;
|
||||
} else if ((pe = getprotobyname(*av)) != NULL) {
|
||||
rule.fw_prot = pe->p_proto; av++; ac--;
|
||||
} else {
|
||||
show_usage("invalid protocol\n");
|
||||
}
|
||||
} else
|
||||
show_usage("missing protocol\n");
|
||||
}
|
||||
|
||||
/* from */
|
||||
if (ac && !strncmp(*av,"from",strlen(*av))) { av++; ac--; }
|
||||
@ -723,9 +680,9 @@ add(ac,av)
|
||||
av++; ac--;
|
||||
}
|
||||
|
||||
if ((rule.fw_flg & IP_FW_F_KIND) != IP_FW_F_TCP &&
|
||||
(rule.fw_flg & IP_FW_F_KIND) != IP_FW_F_UDP &&
|
||||
(rule.fw_nsp || rule.fw_ndp)) {
|
||||
if ((rule.fw_prot != IPPROTO_TCP) &&
|
||||
(rule.fw_prot != IPPROTO_UDP) &&
|
||||
(rule.fw_nsp || rule.fw_ndp)) {
|
||||
show_usage("only TCP and UDP protocols are valid with port specifications");
|
||||
}
|
||||
|
||||
@ -768,7 +725,7 @@ add(ac,av)
|
||||
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 (rule.fw_prot == IPPROTO_TCP) {
|
||||
if (!strncmp(*av,"established",strlen(*av))) {
|
||||
rule.fw_tcpf |= IP_FW_TCPF_ESTAB;
|
||||
av++; ac--; continue;
|
||||
@ -784,20 +741,13 @@ add(ac,av)
|
||||
av++; ac--; continue;
|
||||
}
|
||||
}
|
||||
if ((rule.fw_flg & IP_FW_F_KIND) == IP_FW_F_ICMP) {
|
||||
if (rule.fw_prot == IPPROTO_ICMP) {
|
||||
if (ac > 1 && !strncmp(*av,"icmptypes",strlen(*av))) {
|
||||
av++; ac--;
|
||||
fill_icmptypes(rule.fw_icmptypes, av, &rule.fw_flg);
|
||||
av++; ac--; continue;
|
||||
}
|
||||
}
|
||||
if ((rule.fw_flg & IP_FW_F_KIND) == IP_FW_F_ALL) {
|
||||
if (ac > 1 && !strncmp(*av,"proto",strlen(*av))) {
|
||||
av++; ac--;
|
||||
fill_port(&rule.fw_nsp, &rule.fw_pts, 0, *av, 1);
|
||||
av++; ac--; continue;
|
||||
}
|
||||
}
|
||||
printf("%d %s\n",ac,*av);
|
||||
show_usage("Unknown argument\n");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user