Summary: This diff introduces a -P flag to pfctl for situations when
it is helpful to display all ports as numbers in "pfctl -sr" output.
Details:
When writing firewall rules or troubleshooting tricky network
issues, it is often helpful to confirm that the loaded PF ruleset
actually matches the original rules specified in pf.conf.
However, the current behavior of "pfctl -sr" of showing ports as
names (e.g. port 80 is printed as "port = www") makes it challenging
to do this confirmation, especially if the rules in pf.conf specify
ports as numbers.
For example, suppose we have loaded the following sample pf.conf
where all the ports are written as numbers:
# cat pf.conf
block in quick on em0 proto tcp to port 445
block in quick on em0 proto tcp to port 139
block in quick on em0 proto tcp to port 3031
pass in on em0 proto tcp from port 5680 to port 521
pass in on em0 proto tcp to port 4399
pass in on em0 proto tcp to port 80
pass in on em0 proto tcp to port 2817
"pfctl -sr" will show the ports according to their names in
/etc/services if available:
# pfctl -f pf.conf
# pfctl -sr
block drop in quick on em0 proto tcp from any to any port = microsoft-ds
block drop in quick on em0 proto tcp from any to any port = netbios-ssn
block drop in quick on em0 proto tcp from any to any port = eppc
pass in on em0 proto tcp from any port = canna to any port = efs flags S/SA
keep state
pass in on em0 proto tcp from any to any port = 4399 flags S/SA keep state
pass in on em0 proto tcp from any to any port = www flags S/SA keep state
pass in on em0 proto tcp from any to any port = 2817 flags S/SA keep state
It is unclear from the above output whether the loaded ruleset
matches the original pf.conf, especially for less familiar ports
like ports 3031 and 5680, which are shown as "eppc" and "canna".
To resolve this, the attached diff introduces a -P flag to pfctl
that is useful in situations when it would be helpful to see the
ports as numbers:
# pfctl -P -sr
block drop in quick on em0 proto tcp from any to any port = 445
block drop in quick on em0 proto tcp from any to any port = 139
block drop in quick on em0 proto tcp from any to any port = 3031
pass in on em0 proto tcp from any port = 5680 to any port = 521 flags S/SA keep
state
pass in on em0 proto tcp from any to any port = 4399 flags S/SA keep state
pass in on em0 proto tcp from any to any port = 80 flags S/SA keep state
pass in on em0 proto tcp from any to any port = 2817 flags S/SA keep state
A note on the diff: To implement this, I had to pass the opts
variable that represents various pfctl command-line options all the
way to print_port(). I wanted to preserve the convention of letting
this opts variable be the last argument in almost all functions in
pfctl.c. Since print_rule() also has a local variable named opts, I
chose to rename print_rule()'s local opts variable to rule_opts, so
that I can keep this convention.
Does anyone have thoughts or comments on this diff? I am open to
feedback and suggestions for improvement.
Thank you,
Lawrence
Index: pfctl.8
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl.8,v
retrieving revision 1.154
diff -u -p -r1.154 pfctl.8
--- pfctl.8 23 Apr 2011 10:14:59 -0000 1.154
+++ pfctl.8 24 May 2011 00:51:35 -0000
@@ -33,7 +33,7 @@
.Sh SYNOPSIS
.Nm pfctl
.Bk -words
-.Op Fl deghnqrvz
+.Op Fl deghnPqrvz
.Op Fl a Ar anchor
.Op Fl D Ar macro Ns = Ns Ar value
.Op Fl F Ar modifier
@@ -325,6 +325,9 @@ Enable basic ruleset optimizations with
.El
For further information on the ruleset optimizer, see
.Xr pf.conf 5 .
+.It Fl P
+Always print ports as numbers, even if names exist for them in
+.Pa /etc/services .
.It Fl p Ar device
Use the device file
.Ar device
Index: pfctl.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl.c,v
retrieving revision 1.303
diff -u -p -r1.303 pfctl.c
--- pfctl.c 1 Oct 2010 12:33:14 -0000 1.303
+++ pfctl.c 24 May 2011 00:51:35 -0000
@@ -232,7 +232,7 @@ usage(void)
{
extern char *__progname;
- fprintf(stderr, "usage: %s [-deghnqrvz] ", __progname);
+ fprintf(stderr, "usage: %s [-deghnPqrvz] ", __progname);
fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
fprintf(stderr, "\t[-f file] [-i interface] [-K host | network]\n");
fprintf(stderr, "\t[-k host | network | label | id] ");
@@ -884,7 +884,7 @@ pfctl_show_rules(int dev, char *path, in
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
labels = 1;
INDENT(depth, !(opts & PF_OPT_VERBOSE));
- print_rule(&pr.rule, pr.anchor_call, rule_numbers);
+ print_rule(&pr.rule, pr.anchor_call, rule_numbers,
opts);
/*
* If this is a 'unnamed' brace notation
@@ -1232,7 +1232,7 @@ pfctl_load_rule(struct pfctl *pf, char *
if (pf->opts & PF_OPT_VERBOSE) {
INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
- print_rule(r, name, pf->opts & PF_OPT_VERBOSE2);
+ print_rule(r, name, pf->opts & PF_OPT_VERBOSE2, pf->opts);
}
path[len] = '\0';
return (0);
@@ -1948,7 +1948,7 @@ main(int argc, char *argv[])
usage();
while ((ch = getopt(argc, argv,
- "a:dD:eqf:F:ghi:k:K:L:no:p:R:rS:s:t:T:vx:z")) != -1) {
+ "a:dD:eqf:F:ghi:k:K:L:no:Pp:R:rS:s:t:T:vx:z")) != -1) {
switch (ch) {
case 'a':
anchoropt = optarg;
@@ -2026,6 +2026,9 @@ main(int argc, char *argv[])
}
opts |= PF_OPT_OPTIMIZE;
break;
+ case 'P':
+ opts |= PF_OPT_NUMERICPORTS;
+ break;
case 'p':
pf_device = optarg;
break;
Index: pfctl_parser.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_parser.c,v
retrieving revision 1.275
diff -u -p -r1.275 pfctl_parser.c
--- pfctl_parser.c 6 Apr 2011 13:19:55 -0000 1.275
+++ pfctl_parser.c 24 May 2011 00:51:36 -0000
@@ -63,11 +63,11 @@
#include "pfctl.h"
void print_op (u_int8_t, const char *, const char *);
-void print_port (u_int8_t, u_int16_t, u_int16_t, const char *);
+void print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int);
void print_ugid (u_int8_t, unsigned, unsigned, const char *,
unsigned);
void print_flags (u_int8_t);
void print_fromto(struct pf_rule_addr *, pf_osfp_t,
- struct pf_rule_addr *, u_int8_t, u_int8_t, int);
+ struct pf_rule_addr *, u_int8_t, u_int8_t, int, int);
int ifa_skip_if(const char *filter, struct node_host *p);
struct node_host *ifa_grouplookup(const char *, int);
@@ -360,12 +360,13 @@ print_op(u_int8_t op, const char *a1, co
}
void
-print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto)
+print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int
opts)
{
char a1[6], a2[6];
- struct servent *s;
+ struct servent *s = NULL;
- s = getservbyport(p1, proto);
+ if (!(opts & PF_OPT_NUMERICPORTS))
+ s = getservbyport(p1, proto);
p1 = ntohs(p1);
p2 = ntohs(p2);
snprintf(a1, sizeof(a1), "%u", p1);
@@ -403,7 +404,7 @@ print_flags(u_int8_t f)
void
print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr
*dst,
- sa_family_t af, u_int8_t proto, int verbose)
+ sa_family_t af, u_int8_t proto, int verbose, int opts)
{
char buf[PF_OSFP_LEN*3];
if (src->addr.type == PF_ADDR_ADDRMASK &&
@@ -424,7 +425,7 @@ print_fromto(struct pf_rule_addr *src, p
if (src->port_op)
print_port(src->port_op, src->port[0],
src->port[1],
- proto == IPPROTO_TCP ? "tcp" : "udp");
+ proto == IPPROTO_TCP ? "tcp" : "udp", opts);
if (osfp != PF_OSFP_ANY)
printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf,
sizeof(buf)));
@@ -436,7 +437,7 @@ print_fromto(struct pf_rule_addr *src, p
if (dst->port_op)
print_port(dst->port_op, dst->port[0],
dst->port[1],
- proto == IPPROTO_TCP ? "tcp" : "udp");
+ proto == IPPROTO_TCP ? "tcp" : "udp", opts);
}
}
@@ -671,7 +672,7 @@ print_src_node(struct pf_src_node *sn, i
}
void
-print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
+print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int opts)
{
static const char *actiontypes[] = { "pass", "block", "scrub",
"no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr",
@@ -679,7 +680,7 @@ print_rule(struct pf_rule *r, const char
static const char *anchortypes[] = { "anchor", "anchor", "anchor",
"anchor", "nat-anchor", "nat-anchor", "binat-anchor",
"binat-anchor", "rdr-anchor", "rdr-anchor" };
- int i, opts;
+ int i, rule_opts;
char *p;
if (verbose)
@@ -792,7 +793,7 @@ print_rule(struct pf_rule *r, const char
printf(" proto %u", r->proto);
}
print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto,
- verbose);
+ verbose, opts);
if (r->rcv_ifname[0])
printf(" received-on %s", r->rcv_ifname);
if (r->uid.op)
@@ -858,72 +859,72 @@ print_rule(struct pf_rule *r, const char
}
printf(" probability %s%%", buf);
}
- opts = 0;
+ rule_opts = 0;
if (r->max_states || r->max_src_nodes || r->max_src_states)
- opts = 1;
+ rule_opts = 1;
if (r->rule_flag & PFRULE_NOSYNC)
- opts = 1;
+ rule_opts = 1;
if (r->rule_flag & PFRULE_SRCTRACK)
- opts = 1;
+ rule_opts = 1;
if (r->rule_flag & PFRULE_IFBOUND)
- opts = 1;
+ rule_opts = 1;
if (r->rule_flag & PFRULE_STATESLOPPY)
- opts = 1;
+ rule_opts = 1;
if (r->rule_flag & PFRULE_PFLOW)
- opts = 1;
- for (i = 0; !opts && i < PFTM_MAX; ++i)
+ rule_opts = 1;
+ for (i = 0; !rule_opts && i < PFTM_MAX; ++i)
if (r->timeout[i])
- opts = 1;
- if (opts) {
+ rule_opts = 1;
+ if (rule_opts) {
printf(" (");
if (r->max_states) {
printf("max %u", r->max_states);
- opts = 0;
+ rule_opts = 0;
}
if (r->rule_flag & PFRULE_NOSYNC) {
- if (!opts)
+ if (!rule_opts)
printf(", ");
printf("no-sync");
- opts = 0;
+ rule_opts = 0;
}
if (r->rule_flag & PFRULE_SRCTRACK) {
- if (!opts)
+ if (!rule_opts)
printf(", ");
printf("source-track");
if (r->rule_flag & PFRULE_RULESRCTRACK)
printf(" rule");
else
printf(" global");
- opts = 0;
+ rule_opts = 0;
}
if (r->max_src_states) {
- if (!opts)
+ if (!rule_opts)
printf(", ");
printf("max-src-states %u", r->max_src_states);
- opts = 0;
+ rule_opts = 0;
}
if (r->max_src_conn) {
- if (!opts)
+ if (!rule_opts)
printf(", ");
printf("max-src-conn %u", r->max_src_conn);
- opts = 0;
+ rule_opts = 0;
}
if (r->max_src_conn_rate.limit) {
- if (!opts)
+ if (!rule_opts)
printf(", ");
printf("max-src-conn-rate %u/%u",
r->max_src_conn_rate.limit,
r->max_src_conn_rate.seconds);
- opts = 0;
+ rule_opts = 0;
}
if (r->max_src_nodes) {
- if (!opts)
+ if (!rule_opts)
printf(", ");
printf("max-src-nodes %u", r->max_src_nodes);
- opts = 0;
+ rule_opts = 0;
}
if (r->overload_tblname[0]) {
- if (!opts)
+ if (!rule_opts)
printf(", ");
printf("overload <%s>", r->overload_tblname);
if (r->flush)
@@ -932,30 +933,30 @@ print_rule(struct pf_rule *r, const char
printf(" global");
}
if (r->rule_flag & PFRULE_IFBOUND) {
- if (!opts)
+ if (!rule_opts)
printf(", ");
printf("if-bound");
- opts = 0;
+ rule_opts = 0;
}
if (r->rule_flag & PFRULE_STATESLOPPY) {
- if (!opts)
+ if (!rule_opts)
printf(", ");
printf("sloppy");
- opts = 0;
+ rule_opts = 0;
}
if (r->rule_flag & PFRULE_PFLOW) {
- if (!opts)
+ if (!rule_opts)
printf(", ");
printf("pflow");
- opts = 0;
+ rule_opts = 0;
}
for (i = 0; i < PFTM_MAX; ++i)
if (r->timeout[i]) {
int j;
- if (!opts)
+ if (!rule_opts)
printf(", ");
- opts = 0;
+ rule_opts = 0;
for (j = 0; pf_timeouts[j].name != NULL;
++j)
if (pf_timeouts[j].timeout == i)
@@ -972,40 +973,40 @@ print_rule(struct pf_rule *r, const char
if (r->scrub_flags >= PFSTATE_NODF || r->min_ttl || r->max_mss) {
printf(" scrub (");
- opts = 1;
+ rule_opts = 1;
if (r->scrub_flags & PFSTATE_NODF) {
printf("no-df");
- opts = 0;
+ rule_opts = 0;
}
if (r->scrub_flags & PFSTATE_RANDOMID) {
- if (!opts)
+ if (!rule_opts)
printf(" ");
printf("random-id");
- opts = 0;
+ rule_opts = 0;
}
if (r->min_ttl) {
- if (!opts)
+ if (!rule_opts)
printf(" ");
printf("min-ttl %d", r->min_ttl);
- opts = 0;
+ rule_opts = 0;
}
if (r->scrub_flags & PFSTATE_SETTOS) {
- if (!opts)
+ if (!rule_opts)
printf(" ");
printf("set-tos 0x%2.2x", r->set_tos);
- opts = 0;
+ rule_opts = 0;
}
if (r->scrub_flags & PFSTATE_SCRUB_TCP) {
- if (!opts)
+ if (!rule_opts)
printf(" ");
printf("reassemble tcp");
- opts = 0;
+ rule_opts = 0;
}
if (r->max_mss) {
- if (!opts)
+ if (!rule_opts)
printf(" ");
printf("max-mss %d", r->max_mss);
- opts = 0;
+ rule_opts = 0;
}
printf(")");
}
Index: pfctl_parser.h
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_parser.h,v
retrieving revision 1.95
diff -u -p -r1.95 pfctl_parser.h
--- pfctl_parser.h 6 Apr 2011 13:19:55 -0000 1.95
+++ pfctl_parser.h 24 May 2011 00:51:36 -0000
@@ -48,6 +48,7 @@
#define PF_OPT_SHOWALL 0x0400
#define PF_OPT_OPTIMIZE 0x0800
#define PF_OPT_RECURSE 0x4000
+#define PF_OPT_NUMERICPORTS 0x8000
#define PF_TH_ALL 0xFF
@@ -216,7 +217,7 @@ int pfctl_load_anchors(int, struct pfctl
void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int,
int);
void print_src_node(struct pf_src_node *, int);
-void print_rule(struct pf_rule *, const char *, int);
+void print_rule(struct pf_rule *, const char *, int, int);
void print_tabledef(const char *, int, int, struct node_tinithead *);
void print_status(struct pf_status *, int);