Resolve conflicts created during the import of pf 3.7 Some features are
missing and will be implemented in a second step. This is functional as is. Tested by: freebsd-pf, pfsense.org Obtained from: OpenBSD
This commit is contained in:
parent
b1feb7cada
commit
0baf7c8675
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=145840
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: authpf.c,v 1.75 2004/01/29 01:55:10 deraadt Exp $ */
|
/* $OpenBSD: authpf.c,v 1.89 2005/02/10 04:24:15 joel Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org).
|
* Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org).
|
||||||
@ -32,7 +32,9 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <net/pfvar.h>
|
#include <net/pfvar.h>
|
||||||
@ -40,6 +42,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <login_cap.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -48,9 +51,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <pfctl_parser.h>
|
|
||||||
#include <pfctl.h>
|
|
||||||
|
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
|
|
||||||
extern int symset(const char *, const char *, int);
|
extern int symset(const char *, const char *, int);
|
||||||
@ -61,11 +61,13 @@ static int allowed_luser(char *);
|
|||||||
static int check_luser(char *, char *);
|
static int check_luser(char *, char *);
|
||||||
static int remove_stale_rulesets(void);
|
static int remove_stale_rulesets(void);
|
||||||
static int change_filter(int, const char *, const char *);
|
static int change_filter(int, const char *, const char *);
|
||||||
|
static int change_table(int, const char *, const char *);
|
||||||
static void authpf_kill_states(void);
|
static void authpf_kill_states(void);
|
||||||
|
|
||||||
int dev; /* pf device */
|
int dev; /* pf device */
|
||||||
char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf";
|
char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf";
|
||||||
char rulesetname[PF_RULESET_NAME_SIZE];
|
char rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2];
|
||||||
|
char tablename[PF_TABLE_NAME_SIZE] = "authpf_users";
|
||||||
|
|
||||||
FILE *pidfp;
|
FILE *pidfp;
|
||||||
char *infile; /* file name printed by yyerror() in parse.y */
|
char *infile; /* file name printed by yyerror() in parse.y */
|
||||||
@ -94,10 +96,12 @@ main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
int lockcnt = 0, n, pidfd;
|
int lockcnt = 0, n, pidfd;
|
||||||
FILE *config;
|
FILE *config;
|
||||||
struct in_addr ina;
|
struct in6_addr ina;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
char *cp;
|
char *cp;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
|
char *shell;
|
||||||
|
login_cap_t *lc;
|
||||||
|
|
||||||
config = fopen(PATH_CONFFILE, "r");
|
config = fopen(PATH_CONFFILE, "r");
|
||||||
|
|
||||||
@ -121,7 +125,8 @@ main(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
if (inet_pton(AF_INET, ipsrc, &ina) != 1) {
|
if (inet_pton(AF_INET, ipsrc, &ina) != 1 &&
|
||||||
|
inet_pton(AF_INET6, ipsrc, &ina) != 1) {
|
||||||
syslog(LOG_ERR,
|
syslog(LOG_ERR,
|
||||||
"cannot determine IP from SSH_CLIENT %s", ipsrc);
|
"cannot determine IP from SSH_CLIENT %s", ipsrc);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -135,16 +140,31 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
uid = getuid();
|
uid = getuid();
|
||||||
pw = getpwuid(uid);
|
pw = getpwuid(uid);
|
||||||
|
endpwent();
|
||||||
if (pw == NULL) {
|
if (pw == NULL) {
|
||||||
syslog(LOG_ERR, "cannot find user for uid %u", uid);
|
syslog(LOG_ERR, "cannot find user for uid %u", uid);
|
||||||
goto die;
|
goto die;
|
||||||
}
|
}
|
||||||
if (strcmp(pw->pw_shell, PATH_AUTHPF_SHELL)) {
|
|
||||||
|
if ((lc = login_getclass(pw->pw_class)) != NULL)
|
||||||
|
shell = (char *)login_getcapstr(lc, "shell", pw->pw_shell,
|
||||||
|
pw->pw_shell);
|
||||||
|
else
|
||||||
|
shell = pw->pw_shell;
|
||||||
|
|
||||||
|
login_close(lc);
|
||||||
|
|
||||||
|
if (strcmp(shell, PATH_AUTHPF_SHELL)) {
|
||||||
syslog(LOG_ERR, "wrong shell for user %s, uid %u",
|
syslog(LOG_ERR, "wrong shell for user %s, uid %u",
|
||||||
pw->pw_name, pw->pw_uid);
|
pw->pw_name, pw->pw_uid);
|
||||||
|
if (shell != pw->pw_shell)
|
||||||
|
free(shell);
|
||||||
goto die;
|
goto die;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shell != pw->pw_shell)
|
||||||
|
free(shell);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Paranoia, but this data _does_ come from outside authpf, and
|
* Paranoia, but this data _does_ come from outside authpf, and
|
||||||
* truncation would be bad.
|
* truncation would be bad.
|
||||||
@ -155,11 +175,11 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((n = snprintf(rulesetname, sizeof(rulesetname), "%s(%ld)",
|
if ((n = snprintf(rulesetname, sizeof(rulesetname), "%s(%ld)",
|
||||||
luser, (long)getpid())) < 0 || n >= sizeof(rulesetname)) {
|
luser, (long)getpid())) < 0 || (u_int)n >= sizeof(rulesetname)) {
|
||||||
syslog(LOG_INFO, "%s(%ld) too large, ruleset name will be %ld",
|
syslog(LOG_INFO, "%s(%ld) too large, ruleset name will be %ld",
|
||||||
luser, (long)getpid(), (long)getpid());
|
luser, (long)getpid(), (long)getpid());
|
||||||
if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld",
|
if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld",
|
||||||
(long)getpid())) < 0 || n >= sizeof(rulesetname)) {
|
(long)getpid())) < 0 || (u_int)n >= sizeof(rulesetname)) {
|
||||||
syslog(LOG_ERR, "pid too large for ruleset name");
|
syslog(LOG_ERR, "pid too large for ruleset name");
|
||||||
goto die;
|
goto die;
|
||||||
}
|
}
|
||||||
@ -269,12 +289,17 @@ main(int argc, char *argv[])
|
|||||||
rewind(pidfp);
|
rewind(pidfp);
|
||||||
fprintf(pidfp, "%ld\n%s\n", (long)getpid(), luser);
|
fprintf(pidfp, "%ld\n%s\n", (long)getpid(), luser);
|
||||||
fflush(pidfp);
|
fflush(pidfp);
|
||||||
(void) ftruncate(fileno(pidfp), ftell(pidfp));
|
(void) ftruncate(fileno(pidfp), ftello(pidfp));
|
||||||
|
|
||||||
if (change_filter(1, luser, ipsrc) == -1) {
|
if (change_filter(1, luser, ipsrc) == -1) {
|
||||||
printf("Unable to modify filters\r\n");
|
printf("Unable to modify filters\r\n");
|
||||||
do_death(0);
|
do_death(0);
|
||||||
}
|
}
|
||||||
|
if (change_table(1, luser, ipsrc) == -1) {
|
||||||
|
printf("Unable to modify table\r\n");
|
||||||
|
change_filter(0, luser, ipsrc);
|
||||||
|
do_death(0);
|
||||||
|
}
|
||||||
|
|
||||||
signal(SIGTERM, need_death);
|
signal(SIGTERM, need_death);
|
||||||
signal(SIGINT, need_death);
|
signal(SIGINT, need_death);
|
||||||
@ -284,7 +309,7 @@ main(int argc, char *argv[])
|
|||||||
signal(SIGSTOP, need_death);
|
signal(SIGSTOP, need_death);
|
||||||
signal(SIGTSTP, need_death);
|
signal(SIGTSTP, need_death);
|
||||||
while (1) {
|
while (1) {
|
||||||
printf("\r\nHello %s, ", luser);
|
printf("\r\nHello %s. ", luser);
|
||||||
printf("You are authenticated from host \"%s\"\r\n", ipsrc);
|
printf("You are authenticated from host \"%s\"\r\n", ipsrc);
|
||||||
setproctitle("%s@%s", luser, ipsrc);
|
setproctitle("%s@%s", luser, ipsrc);
|
||||||
print_message(PATH_MESSAGE);
|
print_message(PATH_MESSAGE);
|
||||||
@ -359,6 +384,11 @@ read_config(FILE *f)
|
|||||||
sizeof(anchorname)) >= sizeof(anchorname))
|
sizeof(anchorname)) >= sizeof(anchorname))
|
||||||
goto parse_error;
|
goto parse_error;
|
||||||
}
|
}
|
||||||
|
if (strcasecmp(pair[0], "table") == 0) {
|
||||||
|
if (!pair[1][0] || strlcpy(tablename, pair[1],
|
||||||
|
sizeof(tablename)) >= sizeof(tablename))
|
||||||
|
goto parse_error;
|
||||||
|
}
|
||||||
} while (!feof(f) && !ferror(f));
|
} while (!feof(f) && !ferror(f));
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return (0);
|
return (0);
|
||||||
@ -542,12 +572,10 @@ static int
|
|||||||
remove_stale_rulesets(void)
|
remove_stale_rulesets(void)
|
||||||
{
|
{
|
||||||
struct pfioc_ruleset prs;
|
struct pfioc_ruleset prs;
|
||||||
const int action[PF_RULESET_MAX] = { PF_SCRUB,
|
|
||||||
PF_PASS, PF_NAT, PF_BINAT, PF_RDR };
|
|
||||||
u_int32_t nr, mnr;
|
u_int32_t nr, mnr;
|
||||||
|
|
||||||
memset(&prs, 0, sizeof(prs));
|
memset(&prs, 0, sizeof(prs));
|
||||||
strlcpy(prs.anchor, anchorname, sizeof(prs.anchor));
|
strlcpy(prs.path, anchorname, sizeof(prs.path));
|
||||||
if (ioctl(dev, DIOCGETRULESETS, &prs)) {
|
if (ioctl(dev, DIOCGETRULESETS, &prs)) {
|
||||||
if (errno == EINVAL)
|
if (errno == EINVAL)
|
||||||
return (0);
|
return (0);
|
||||||
@ -574,20 +602,25 @@ remove_stale_rulesets(void)
|
|||||||
(*s && (t == prs.name || *s != ')')))
|
(*s && (t == prs.name || *s != ')')))
|
||||||
return (1);
|
return (1);
|
||||||
if (kill(pid, 0) && errno != EPERM) {
|
if (kill(pid, 0) && errno != EPERM) {
|
||||||
int i;
|
int i;
|
||||||
|
struct pfioc_trans_e t_e[PF_RULESET_MAX+1];
|
||||||
|
struct pfioc_trans t;
|
||||||
|
|
||||||
for (i = 0; i < PF_RULESET_MAX; ++i) {
|
bzero(&t, sizeof(t));
|
||||||
struct pfioc_rule pr;
|
bzero(t_e, sizeof(t_e));
|
||||||
|
t.size = PF_RULESET_MAX+1;
|
||||||
memset(&pr, 0, sizeof(pr));
|
t.esize = sizeof(t_e[0]);
|
||||||
memcpy(pr.anchor, prs.anchor, sizeof(pr.anchor));
|
t.array = t_e;
|
||||||
memcpy(pr.ruleset, prs.name, sizeof(pr.ruleset));
|
for (i = 0; i < PF_RULESET_MAX+1; ++i) {
|
||||||
pr.rule.action = action[i];
|
t_e[i].rs_num = i;
|
||||||
if ((ioctl(dev, DIOCBEGINRULES, &pr) ||
|
snprintf(t_e[i].anchor, sizeof(t_e[i].anchor),
|
||||||
ioctl(dev, DIOCCOMMITRULES, &pr)) &&
|
"%s/%s", anchorname, prs.name);
|
||||||
errno != EINVAL)
|
|
||||||
return (1);
|
|
||||||
}
|
}
|
||||||
|
t_e[PF_RULESET_MAX].rs_num = PF_RULESET_TABLE;
|
||||||
|
if ((ioctl(dev, DIOCXBEGIN, &t) ||
|
||||||
|
ioctl(dev, DIOCXCOMMIT, &t)) &&
|
||||||
|
errno != EINVAL)
|
||||||
|
return (1);
|
||||||
mnr--;
|
mnr--;
|
||||||
} else
|
} else
|
||||||
nr++;
|
nr++;
|
||||||
@ -601,85 +634,67 @@ remove_stale_rulesets(void)
|
|||||||
static int
|
static int
|
||||||
change_filter(int add, const char *luser, const char *ipsrc)
|
change_filter(int add, const char *luser, const char *ipsrc)
|
||||||
{
|
{
|
||||||
char fn[MAXPATHLEN];
|
char *pargv[13] = {
|
||||||
FILE *f = NULL;
|
"pfctl", "-p", "/dev/pf", "-q", "-a", "anchor/ruleset",
|
||||||
struct pfctl pf;
|
"-D", "user_ip=X", "-D", "user_id=X", "-f",
|
||||||
struct pfr_buffer t;
|
"file", NULL
|
||||||
int i;
|
};
|
||||||
|
char *fdpath = NULL, *userstr = NULL, *ipstr = NULL;
|
||||||
|
char *rsn = NULL, *fn = NULL;
|
||||||
|
pid_t pid;
|
||||||
|
int s;
|
||||||
|
|
||||||
if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
|
if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
|
||||||
syslog(LOG_ERR, "invalid luser/ipsrc");
|
syslog(LOG_ERR, "invalid luser/ipsrc");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add) {
|
if (asprintf(&rsn, "%s/%s", anchorname, rulesetname) == -1)
|
||||||
if ((i = snprintf(fn, sizeof(fn), "%s/%s/authpf.rules",
|
goto no_mem;
|
||||||
PATH_USER_DIR, luser)) < 0 || i >= sizeof(fn)) {
|
if (asprintf(&fdpath, "/dev/fd/%d", dev) == -1)
|
||||||
syslog(LOG_ERR, "user rule path too long");
|
goto no_mem;
|
||||||
goto error;
|
if (asprintf(&ipstr, "user_ip=%s", ipsrc) == -1)
|
||||||
}
|
goto no_mem;
|
||||||
if ((f = fopen(fn, "r")) == NULL && errno != ENOENT) {
|
if (asprintf(&userstr, "user_id=%s", luser) == -1)
|
||||||
syslog(LOG_ERR, "cannot open %s (%m)", fn);
|
goto no_mem;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (f == NULL) {
|
|
||||||
if (strlcpy(fn, PATH_PFRULES, sizeof(fn)) >=
|
|
||||||
sizeof(fn)) {
|
|
||||||
syslog(LOG_ERR, "rule path too long");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if ((f = fopen(fn, "r")) == NULL) {
|
|
||||||
syslog(LOG_ERR, "cannot open %s (%m)", fn);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pfctl_load_fingerprints(dev, 0)) {
|
|
||||||
syslog(LOG_ERR, "unable to load kernel's OS fingerprints");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
bzero(&t, sizeof(t));
|
|
||||||
t.pfrb_type = PFRB_TRANS;
|
|
||||||
memset(&pf, 0, sizeof(pf));
|
|
||||||
for (i = 0; i < PF_RULESET_MAX; ++i) {
|
|
||||||
if (pfctl_add_trans(&t, i, anchorname, rulesetname)) {
|
|
||||||
syslog(LOG_ERR, "pfctl_add_trans %m");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pfctl_trans(dev, &t, DIOCXBEGIN, 0)) {
|
|
||||||
syslog(LOG_ERR, "DIOCXBEGIN (%s) %m", add?"add":"remove");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (add) {
|
if (add) {
|
||||||
if (symset("user_ip", ipsrc, 0) ||
|
struct stat sb;
|
||||||
symset("user_id", luser, 0)) {
|
|
||||||
syslog(LOG_ERR, "symset");
|
if (asprintf(&fn, "%s/%s/authpf.rules", PATH_USER_DIR, luser)
|
||||||
goto error;
|
== -1)
|
||||||
|
goto no_mem;
|
||||||
|
if (stat(fn, &sb) == -1) {
|
||||||
|
free(fn);
|
||||||
|
if ((fn = strdup(PATH_PFRULES)) == NULL)
|
||||||
|
goto no_mem;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
pargv[2] = fdpath;
|
||||||
|
pargv[5] = rsn;
|
||||||
|
pargv[7] = userstr;
|
||||||
|
pargv[9] = ipstr;
|
||||||
|
if (!add)
|
||||||
|
pargv[11] = "/dev/null";
|
||||||
|
else
|
||||||
|
pargv[11] = fn;
|
||||||
|
|
||||||
pf.dev = dev;
|
switch (pid = fork()) {
|
||||||
pf.trans = &t;
|
case -1:
|
||||||
pf.anchor = anchorname;
|
err(1, "fork failed");
|
||||||
pf.ruleset = rulesetname;
|
case 0:
|
||||||
|
execvp(PATH_PFCTL, pargv);
|
||||||
infile = fn;
|
warn("exec of %s failed", PATH_PFCTL);
|
||||||
if (parse_rules(f, &pf) < 0) {
|
_exit(1);
|
||||||
syslog(LOG_ERR, "syntax error in rule file: "
|
|
||||||
"authpf rules not loaded");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
infile = NULL;
|
|
||||||
fclose(f);
|
|
||||||
f = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) {
|
/* parent */
|
||||||
syslog(LOG_ERR, "DIOCXCOMMIT (%s) %m", add?"add":"remove");
|
waitpid(pid, &s, 0);
|
||||||
goto error;
|
if (s != 0) {
|
||||||
|
if (WIFEXITED(s)) {
|
||||||
|
syslog(LOG_ERR, "pfctl exited abnormally");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add) {
|
if (add) {
|
||||||
@ -691,17 +706,62 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
|||||||
ipsrc, luser, Tend.tv_sec - Tstart.tv_sec);
|
ipsrc, luser, Tend.tv_sec - Tstart.tv_sec);
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
|
no_mem:
|
||||||
|
syslog(LOG_ERR, "malloc failed");
|
||||||
error:
|
error:
|
||||||
if (f != NULL)
|
free(fdpath);
|
||||||
fclose(f);
|
fdpath = NULL;
|
||||||
if (pfctl_trans(dev, &t, DIOCXROLLBACK, 0))
|
free(rsn);
|
||||||
syslog(LOG_ERR, "DIOCXROLLBACK (%s) %m", add?"add":"remove");
|
rsn = NULL;
|
||||||
|
free(userstr);
|
||||||
|
userstr = NULL;
|
||||||
|
free(ipstr);
|
||||||
|
ipstr = NULL;
|
||||||
|
free(fn);
|
||||||
|
fn = NULL;
|
||||||
infile = NULL;
|
infile = NULL;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add/remove this IP from the "authpf_users" table.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
change_table(int add, const char *luser, const char *ipsrc)
|
||||||
|
{
|
||||||
|
struct pfioc_table io;
|
||||||
|
struct pfr_addr addr;
|
||||||
|
|
||||||
|
bzero(&io, sizeof(io));
|
||||||
|
strlcpy(io.pfrio_table.pfrt_name, tablename, sizeof(io.pfrio_table));
|
||||||
|
io.pfrio_buffer = &addr;
|
||||||
|
io.pfrio_esize = sizeof(addr);
|
||||||
|
io.pfrio_size = 1;
|
||||||
|
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
if (ipsrc == NULL || !ipsrc[0])
|
||||||
|
return (-1);
|
||||||
|
if (inet_pton(AF_INET, ipsrc, &addr.pfra_ip4addr) == 1) {
|
||||||
|
addr.pfra_af = AF_INET;
|
||||||
|
addr.pfra_net = 32;
|
||||||
|
} else if (inet_pton(AF_INET6, ipsrc, &addr.pfra_ip6addr) == 1) {
|
||||||
|
addr.pfra_af = AF_INET6;
|
||||||
|
addr.pfra_net = 128;
|
||||||
|
} else {
|
||||||
|
syslog(LOG_ERR, "invalid ipsrc");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(dev, add ? DIOCRADDADDRS : DIOCRDELADDRS, &io) &&
|
||||||
|
errno != ESRCH) {
|
||||||
|
syslog(LOG_ERR, "cannot %s %s from table %s: %s",
|
||||||
|
add ? "add" : "remove", ipsrc, tablename,
|
||||||
|
strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is to kill off states that would otherwise be left behind stateful
|
* This is to kill off states that would otherwise be left behind stateful
|
||||||
* rules. This means we don't need to allow in more traffic than we really
|
* rules. This means we don't need to allow in more traffic than we really
|
||||||
@ -713,24 +773,32 @@ static void
|
|||||||
authpf_kill_states(void)
|
authpf_kill_states(void)
|
||||||
{
|
{
|
||||||
struct pfioc_state_kill psk;
|
struct pfioc_state_kill psk;
|
||||||
struct in_addr target;
|
struct pf_addr target;
|
||||||
|
|
||||||
memset(&psk, 0, sizeof(psk));
|
memset(&psk, 0, sizeof(psk));
|
||||||
psk.psk_af = AF_INET;
|
memset(&target, 0, sizeof(target));
|
||||||
|
|
||||||
inet_pton(AF_INET, ipsrc, &target);
|
if (inet_pton(AF_INET, ipsrc, &target.v4) == 1)
|
||||||
|
psk.psk_af = AF_INET;
|
||||||
|
else if (inet_pton(AF_INET6, ipsrc, &target.v6) == 1)
|
||||||
|
psk.psk_af = AF_INET6;
|
||||||
|
else {
|
||||||
|
syslog(LOG_ERR, "inet_pton(%s) failed", ipsrc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Kill all states from ipsrc */
|
/* Kill all states from ipsrc */
|
||||||
psk.psk_src.addr.v.a.addr.v4 = target;
|
memcpy(&psk.psk_src.addr.v.a.addr, &target,
|
||||||
|
sizeof(psk.psk_src.addr.v.a.addr));
|
||||||
memset(&psk.psk_src.addr.v.a.mask, 0xff,
|
memset(&psk.psk_src.addr.v.a.mask, 0xff,
|
||||||
sizeof(psk.psk_src.addr.v.a.mask));
|
sizeof(psk.psk_src.addr.v.a.mask));
|
||||||
if (ioctl(dev, DIOCKILLSTATES, &psk))
|
if (ioctl(dev, DIOCKILLSTATES, &psk))
|
||||||
syslog(LOG_ERR, "DIOCKILLSTATES failed (%m)");
|
syslog(LOG_ERR, "DIOCKILLSTATES failed (%m)");
|
||||||
|
|
||||||
/* Kill all states to ipsrc */
|
/* Kill all states to ipsrc */
|
||||||
psk.psk_af = AF_INET;
|
|
||||||
memset(&psk.psk_src, 0, sizeof(psk.psk_src));
|
memset(&psk.psk_src, 0, sizeof(psk.psk_src));
|
||||||
psk.psk_dst.addr.v.a.addr.v4 = target;
|
memcpy(&psk.psk_dst.addr.v.a.addr, &target,
|
||||||
|
sizeof(psk.psk_dst.addr.v.a.addr));
|
||||||
memset(&psk.psk_dst.addr.v.a.mask, 0xff,
|
memset(&psk.psk_dst.addr.v.a.mask, 0xff,
|
||||||
sizeof(psk.psk_dst.addr.v.a.mask));
|
sizeof(psk.psk_dst.addr.v.a.mask));
|
||||||
if (ioctl(dev, DIOCKILLSTATES, &psk))
|
if (ioctl(dev, DIOCKILLSTATES, &psk))
|
||||||
@ -758,6 +826,7 @@ do_death(int active)
|
|||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
change_filter(0, luser, ipsrc);
|
change_filter(0, luser, ipsrc);
|
||||||
|
change_table(0, luser, ipsrc);
|
||||||
authpf_kill_states();
|
authpf_kill_states();
|
||||||
remove_stale_rulesets();
|
remove_stale_rulesets();
|
||||||
}
|
}
|
||||||
@ -768,157 +837,3 @@ do_death(int active)
|
|||||||
syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile);
|
syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile);
|
||||||
exit(ret);
|
exit(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* callbacks for parse_rules(void)
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
|
|
||||||
{
|
|
||||||
u_int8_t rs_num;
|
|
||||||
struct pfioc_rule pr;
|
|
||||||
|
|
||||||
switch (r->action) {
|
|
||||||
case PF_PASS:
|
|
||||||
case PF_DROP:
|
|
||||||
rs_num = PF_RULESET_FILTER;
|
|
||||||
break;
|
|
||||||
case PF_SCRUB:
|
|
||||||
rs_num = PF_RULESET_SCRUB;
|
|
||||||
break;
|
|
||||||
case PF_NAT:
|
|
||||||
case PF_NONAT:
|
|
||||||
rs_num = PF_RULESET_NAT;
|
|
||||||
break;
|
|
||||||
case PF_RDR:
|
|
||||||
case PF_NORDR:
|
|
||||||
rs_num = PF_RULESET_RDR;
|
|
||||||
break;
|
|
||||||
case PF_BINAT:
|
|
||||||
case PF_NOBINAT:
|
|
||||||
rs_num = PF_RULESET_BINAT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
syslog(LOG_ERR, "invalid rule action %d", r->action);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bzero(&pr, sizeof(pr));
|
|
||||||
strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor));
|
|
||||||
strlcpy(pr.ruleset, pf->ruleset, sizeof(pr.ruleset));
|
|
||||||
if (pfctl_add_pool(pf, &r->rpool, r->af))
|
|
||||||
return (1);
|
|
||||||
pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor,
|
|
||||||
pf->ruleset);
|
|
||||||
pr.pool_ticket = pf->paddr.ticket;
|
|
||||||
memcpy(&pr.rule, r, sizeof(pr.rule));
|
|
||||||
if (ioctl(pf->dev, DIOCADDRULE, &pr)) {
|
|
||||||
syslog(LOG_ERR, "DIOCADDRULE %m");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
pfctl_clear_pool(&r->rpool);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af)
|
|
||||||
{
|
|
||||||
struct pf_pooladdr *pa;
|
|
||||||
|
|
||||||
if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) {
|
|
||||||
syslog(LOG_ERR, "DIOCBEGINADDRS %m");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
pf->paddr.af = af;
|
|
||||||
TAILQ_FOREACH(pa, &p->list, entries) {
|
|
||||||
memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr));
|
|
||||||
if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) {
|
|
||||||
syslog(LOG_ERR, "DIOCADDADDR %m");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pfctl_clear_pool(struct pf_pool *pool)
|
|
||||||
{
|
|
||||||
struct pf_pooladdr *pa;
|
|
||||||
|
|
||||||
while ((pa = TAILQ_FIRST(&pool->list)) != NULL) {
|
|
||||||
TAILQ_REMOVE(&pool->list, pa, entries);
|
|
||||||
free(pa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "altq rules not supported in authpf\n");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pfctl_set_optimization(struct pfctl *pf, const char *opt)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "set optimization not supported in authpf\n");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pfctl_set_logif(struct pfctl *pf, char *ifname)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "set loginterface not supported in authpf\n");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "set hostid not supported in authpf\n");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "set timeout not supported in authpf\n");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "set limit not supported in authpf\n");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pfctl_set_debug(struct pfctl *pf, char *d)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "set debug not supported in authpf\n");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
|
||||||
const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "table definitions not yet supported in authpf\n");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pfctl_rules(int dev, char *filename, int opts, char *anchorname,
|
|
||||||
char *rulesetname, struct pfr_buffer *t)
|
|
||||||
{
|
|
||||||
/* never called, no anchors inside anchors, but we need the stub */
|
|
||||||
fprintf(stderr, "load anchor not supported from authpf\n");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pfctl_print_title(char *title)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: ftp-proxy.8,v 1.40 2004/03/16 08:50:07 jmc Exp $
|
.\" $OpenBSD: ftp-proxy.8,v 1.42 2004/11/19 00:47:23 jmc Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 1996-2001
|
.\" Copyright (c) 1996-2001
|
||||||
.\" Obtuse Systems Corporation, All rights reserved.
|
.\" Obtuse Systems Corporation, All rights reserved.
|
||||||
@ -37,14 +37,18 @@
|
|||||||
.Nd Internet File Transfer Protocol proxy server
|
.Nd Internet File Transfer Protocol proxy server
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm ftp-proxy
|
.Nm ftp-proxy
|
||||||
|
.Bk -words
|
||||||
.Op Fl AnrVw
|
.Op Fl AnrVw
|
||||||
.Op Fl a Ar address
|
.Op Fl a Ar address
|
||||||
.Op Fl D Ar debuglevel
|
.Op Fl D Ar debuglevel
|
||||||
.Op Fl g Ar group
|
.Op Fl g Ar group
|
||||||
.Op Fl M Ar maxport
|
.Op Fl M Ar maxport
|
||||||
.Op Fl m Ar minport
|
.Op Fl m Ar minport
|
||||||
|
.Op Fl R Ar address[:port]
|
||||||
|
.Op Fl S Ar address
|
||||||
.Op Fl t Ar timeout
|
.Op Fl t Ar timeout
|
||||||
.Op Fl u Ar user
|
.Op Fl u Ar user
|
||||||
|
.Ek
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
is a proxy for the Internet File Transfer Protocol.
|
is a proxy for the Internet File Transfer Protocol.
|
||||||
@ -139,12 +143,27 @@ Without this flag,
|
|||||||
does not require any IP forwarding or NAT beyond the
|
does not require any IP forwarding or NAT beyond the
|
||||||
.Em rdr
|
.Em rdr
|
||||||
necessary to capture the FTP control connection.
|
necessary to capture the FTP control connection.
|
||||||
|
.It Fl R Ar address:[port]
|
||||||
|
Reverse proxy mode for FTP servers running behind a NAT gateway.
|
||||||
|
In this mode, no redirection is needed.
|
||||||
|
The proxy is run from
|
||||||
|
.Xr inetd 8
|
||||||
|
on the port that external clients connect to (usually 21).
|
||||||
|
Control connections and passive data connections are forwarded
|
||||||
|
to the server.
|
||||||
.It Fl r
|
.It Fl r
|
||||||
Use reverse host
|
Use reverse host
|
||||||
.Pq reverse DNS
|
.Pq reverse DNS
|
||||||
lookups for logging and libwrap use.
|
lookups for logging and libwrap use.
|
||||||
By default,
|
By default,
|
||||||
the proxy does not look up hostnames for libwrap or logging purposes.
|
the proxy does not look up hostnames for libwrap or logging purposes.
|
||||||
|
.It Fl S Ar address
|
||||||
|
Source address to use for data connections made by the proxy.
|
||||||
|
Useful when there are multiple addresses (aliases) available
|
||||||
|
to the proxy.
|
||||||
|
Clients may expect data connections to have the same source
|
||||||
|
address as the control connections, and reject or drop other
|
||||||
|
connections.
|
||||||
.It Fl t Ar timeout
|
.It Fl t Ar timeout
|
||||||
Specifies a timeout, in seconds.
|
Specifies a timeout, in seconds.
|
||||||
The proxy will exit and close open connections if it sees no data
|
The proxy will exit and close open connections if it sees no data
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ftp-proxy.c,v 1.35 2004/03/14 21:51:44 dhartmei Exp $ */
|
/* $OpenBSD: ftp-proxy.c,v 1.41 2005/03/05 23:11:19 cloder Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1996-2001
|
* Copyright (c) 1996-2001
|
||||||
@ -131,6 +131,8 @@ double xfer_start_time;
|
|||||||
struct sockaddr_in real_server_sa;
|
struct sockaddr_in real_server_sa;
|
||||||
struct sockaddr_in client_listen_sa;
|
struct sockaddr_in client_listen_sa;
|
||||||
struct sockaddr_in server_listen_sa;
|
struct sockaddr_in server_listen_sa;
|
||||||
|
struct sockaddr_in proxy_sa;
|
||||||
|
struct in_addr src_addr;
|
||||||
|
|
||||||
int client_listen_socket = -1; /* Only used in PASV mode */
|
int client_listen_socket = -1; /* Only used in PASV mode */
|
||||||
int client_data_socket = -1; /* Connected socket to real client */
|
int client_data_socket = -1; /* Connected socket to real client */
|
||||||
@ -141,13 +143,14 @@ int client_data_bytes, server_data_bytes;
|
|||||||
int AnonFtpOnly;
|
int AnonFtpOnly;
|
||||||
int Verbose;
|
int Verbose;
|
||||||
int NatMode;
|
int NatMode;
|
||||||
|
int ReverseMode;
|
||||||
|
|
||||||
char ClientName[NI_MAXHOST];
|
char ClientName[NI_MAXHOST];
|
||||||
char RealServerName[NI_MAXHOST];
|
char RealServerName[NI_MAXHOST];
|
||||||
char OurName[NI_MAXHOST];
|
char OurName[NI_MAXHOST];
|
||||||
|
|
||||||
char *User = "proxy";
|
const char *User = "proxy";
|
||||||
char *Group;
|
const char *Group;
|
||||||
|
|
||||||
extern int Debug_Level;
|
extern int Debug_Level;
|
||||||
extern int Use_Rdns;
|
extern int Use_Rdns;
|
||||||
@ -175,8 +178,9 @@ static void
|
|||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE,
|
syslog(LOG_NOTICE,
|
||||||
"usage: %s [-AnrVw] [-a address] [-D debuglevel [-g group]"
|
"usage: %s [-AnrVw] [-a address] [-D debuglevel] [-g group]"
|
||||||
" [-M maxport] [-m minport] [-t timeout] [-u user]", __progname);
|
" [-M maxport] [-m minport] [-R address[:port]] [-S address]"
|
||||||
|
" [-t timeout] [-u user]", __progname);
|
||||||
exit(EX_USAGE);
|
exit(EX_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,7 +320,7 @@ show_xfer_stats(void)
|
|||||||
char tbuf[1000];
|
char tbuf[1000];
|
||||||
double delta;
|
double delta;
|
||||||
size_t len;
|
size_t len;
|
||||||
int i;
|
int i = -1;
|
||||||
|
|
||||||
if (!Verbose)
|
if (!Verbose)
|
||||||
return;
|
return;
|
||||||
@ -343,21 +347,21 @@ show_xfer_stats(void)
|
|||||||
"data transfer complete (%dh %dm %ds",
|
"data transfer complete (%dh %dm %ds",
|
||||||
idelta / (60*60), (idelta % (60*60)) / 60,
|
idelta / (60*60), (idelta % (60*60)) / 60,
|
||||||
idelta % 60);
|
idelta % 60);
|
||||||
if (i >= len)
|
if (i == -1 || i >= len)
|
||||||
goto logit;
|
goto logit;
|
||||||
len -= i;
|
len -= i;
|
||||||
} else {
|
} else {
|
||||||
i = snprintf(tbuf, len,
|
i = snprintf(tbuf, len,
|
||||||
"data transfer complete (%dm %ds", idelta / 60,
|
"data transfer complete (%dm %ds", idelta / 60,
|
||||||
idelta % 60);
|
idelta % 60);
|
||||||
if (i >= len)
|
if (i == -1 || i >= len)
|
||||||
goto logit;
|
goto logit;
|
||||||
len -= i;
|
len -= i;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i = snprintf(tbuf, len, "data transfer complete (%.1fs",
|
i = snprintf(tbuf, len, "data transfer complete (%.1fs",
|
||||||
delta);
|
delta);
|
||||||
if (i >= len)
|
if (i == -1 || i >= len)
|
||||||
goto logit;
|
goto logit;
|
||||||
len -= i;
|
len -= i;
|
||||||
}
|
}
|
||||||
@ -366,7 +370,7 @@ show_xfer_stats(void)
|
|||||||
i = snprintf(&tbuf[strlen(tbuf)], len,
|
i = snprintf(&tbuf[strlen(tbuf)], len,
|
||||||
", %d bytes to server) (%.1fKB/s", client_data_bytes,
|
", %d bytes to server) (%.1fKB/s", client_data_bytes,
|
||||||
(client_data_bytes / delta) / (double)1024);
|
(client_data_bytes / delta) / (double)1024);
|
||||||
if (i >= len)
|
if (i == -1 || i >= len)
|
||||||
goto logit;
|
goto logit;
|
||||||
len -= i;
|
len -= i;
|
||||||
}
|
}
|
||||||
@ -374,20 +378,21 @@ show_xfer_stats(void)
|
|||||||
i = snprintf(&tbuf[strlen(tbuf)], len,
|
i = snprintf(&tbuf[strlen(tbuf)], len,
|
||||||
", %d bytes to client) (%.1fKB/s", server_data_bytes,
|
", %d bytes to client) (%.1fKB/s", server_data_bytes,
|
||||||
(server_data_bytes / delta) / (double)1024);
|
(server_data_bytes / delta) / (double)1024);
|
||||||
if (i >= len)
|
if (i == -1 || i >= len)
|
||||||
goto logit;
|
goto logit;
|
||||||
len -= i;
|
len -= i;
|
||||||
}
|
}
|
||||||
strlcat(tbuf, ")", sizeof(tbuf));
|
strlcat(tbuf, ")", sizeof(tbuf));
|
||||||
logit:
|
logit:
|
||||||
syslog(LOG_INFO, "%s", tbuf);
|
if (i != -1)
|
||||||
|
syslog(LOG_INFO, "%s", tbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
log_control_command (char *cmd, int client)
|
log_control_command (char *cmd, int client)
|
||||||
{
|
{
|
||||||
/* log an ftp control command or reply */
|
/* log an ftp control command or reply */
|
||||||
char *logstring;
|
const char *logstring;
|
||||||
int level = LOG_DEBUG;
|
int level = LOG_DEBUG;
|
||||||
|
|
||||||
if (!Verbose)
|
if (!Verbose)
|
||||||
@ -540,7 +545,7 @@ connect_port_backchannel(void)
|
|||||||
* getting one bound to port 20 - This is deliberately
|
* getting one bound to port 20 - This is deliberately
|
||||||
* not RFC compliant.
|
* not RFC compliant.
|
||||||
*/
|
*/
|
||||||
bzero(&listen_sa.sin_addr, sizeof(struct in_addr));
|
bcopy(&src_addr, &listen_sa.sin_addr, sizeof(struct in_addr));
|
||||||
client_data_socket = get_backchannel_socket(SOCK_STREAM,
|
client_data_socket = get_backchannel_socket(SOCK_STREAM,
|
||||||
min_port, max_port, -1, 1, &listen_sa);
|
min_port, max_port, -1, 1, &listen_sa);
|
||||||
if (client_data_socket < 0) {
|
if (client_data_socket < 0) {
|
||||||
@ -558,7 +563,7 @@ connect_port_backchannel(void)
|
|||||||
|
|
||||||
salen = 1;
|
salen = 1;
|
||||||
listen_sa.sin_family = AF_INET;
|
listen_sa.sin_family = AF_INET;
|
||||||
bzero(&listen_sa.sin_addr, sizeof(struct in_addr));
|
bcopy(&src_addr, &listen_sa.sin_addr, sizeof(struct in_addr));
|
||||||
listen_sa.sin_port = htons(20);
|
listen_sa.sin_port = htons(20);
|
||||||
|
|
||||||
if (setsockopt(client_data_socket, SOL_SOCKET, SO_REUSEADDR,
|
if (setsockopt(client_data_socket, SOL_SOCKET, SO_REUSEADDR,
|
||||||
@ -928,7 +933,10 @@ do_server_reply(struct csiob *server, struct csiob *client)
|
|||||||
|
|
||||||
new_dataconn(0);
|
new_dataconn(0);
|
||||||
connection_mode = PASV_MODE;
|
connection_mode = PASV_MODE;
|
||||||
iap = &(server->sa.sin_addr);
|
if (ReverseMode)
|
||||||
|
iap = &(proxy_sa.sin_addr);
|
||||||
|
else
|
||||||
|
iap = &(server->sa.sin_addr);
|
||||||
|
|
||||||
debuglog(1, "we want client to use %s:%u", inet_ntoa(*iap),
|
debuglog(1, "we want client to use %s:%u", inet_ntoa(*iap),
|
||||||
htons(client_listen_sa.sin_port));
|
htons(client_listen_sa.sin_port));
|
||||||
@ -976,7 +984,7 @@ main(int argc, char *argv[])
|
|||||||
int use_tcpwrapper = 0;
|
int use_tcpwrapper = 0;
|
||||||
#endif /* LIBWRAP */
|
#endif /* LIBWRAP */
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "a:D:g:m:M:t:u:AnVwr")) != -1) {
|
while ((ch = getopt(argc, argv, "a:D:g:m:M:R:S:t:u:AnVwr")) != -1) {
|
||||||
char *p;
|
char *p;
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'a':
|
case 'a':
|
||||||
@ -1019,6 +1027,41 @@ main(int argc, char *argv[])
|
|||||||
case 'r':
|
case 'r':
|
||||||
Use_Rdns = 1; /* look up hostnames */
|
Use_Rdns = 1; /* look up hostnames */
|
||||||
break;
|
break;
|
||||||
|
case 'R': {
|
||||||
|
char *s, *t;
|
||||||
|
|
||||||
|
if (!*optarg)
|
||||||
|
usage();
|
||||||
|
if ((s = strdup(optarg)) == NULL) {
|
||||||
|
syslog (LOG_NOTICE,
|
||||||
|
"Insufficient memory (malloc failed)");
|
||||||
|
exit(EX_UNAVAILABLE);
|
||||||
|
}
|
||||||
|
memset(&real_server_sa, 0, sizeof(real_server_sa));
|
||||||
|
real_server_sa.sin_len = sizeof(struct sockaddr_in);
|
||||||
|
real_server_sa.sin_family = AF_INET;
|
||||||
|
t = strchr(s, ':');
|
||||||
|
if (t == NULL)
|
||||||
|
real_server_sa.sin_port = htons(21);
|
||||||
|
else {
|
||||||
|
long port = strtol(t + 1, &p, 10);
|
||||||
|
|
||||||
|
if (*p || port <= 0 || port > 65535)
|
||||||
|
usage();
|
||||||
|
real_server_sa.sin_port = htons(port);
|
||||||
|
*t = 0;
|
||||||
|
}
|
||||||
|
real_server_sa.sin_addr.s_addr = inet_addr(s);
|
||||||
|
if (real_server_sa.sin_addr.s_addr == INADDR_NONE)
|
||||||
|
usage();
|
||||||
|
free(s);
|
||||||
|
ReverseMode = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'S':
|
||||||
|
if (!inet_aton(optarg, &src_addr))
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
timeout_seconds = strtol(optarg, &p, 10);
|
timeout_seconds = strtol(optarg, &p, 10);
|
||||||
if (!*optarg || *p)
|
if (!*optarg || *p)
|
||||||
@ -1054,7 +1097,8 @@ main(int argc, char *argv[])
|
|||||||
memset(&client_iob, 0, sizeof(client_iob));
|
memset(&client_iob, 0, sizeof(client_iob));
|
||||||
memset(&server_iob, 0, sizeof(server_iob));
|
memset(&server_iob, 0, sizeof(server_iob));
|
||||||
|
|
||||||
if (get_proxy_env(0, &real_server_sa, &client_iob.sa) == -1)
|
if (get_proxy_env(0, &real_server_sa, &client_iob.sa,
|
||||||
|
&proxy_sa) == -1)
|
||||||
exit(EX_PROTOCOL);
|
exit(EX_PROTOCOL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -230,7 +230,7 @@ command.
|
|||||||
.Bl -tag -width xxxx
|
.Bl -tag -width xxxx
|
||||||
.It Ar set timeout
|
.It Ar set timeout
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -tag -width interval -compact
|
.Bl -tag -width "src.track" -compact
|
||||||
.It Ar interval
|
.It Ar interval
|
||||||
Interval between purging expired states and fragments.
|
Interval between purging expired states and fragments.
|
||||||
.It Ar frag
|
.It Ar frag
|
||||||
@ -484,6 +484,16 @@ For example:
|
|||||||
.Pp
|
.Pp
|
||||||
.Dl set fingerprints \&"/etc/pf.os.devel\&"
|
.Dl set fingerprints \&"/etc/pf.os.devel\&"
|
||||||
.Pp
|
.Pp
|
||||||
|
.It Ar set skip on <ifspec>
|
||||||
|
List interfaces for which packets should not be filtered.
|
||||||
|
Packets passing in or out on such interfaces are passed as if pf was
|
||||||
|
disabled, i.e. pf does not process them in any way.
|
||||||
|
This can be useful on loopback and other virtual interfaces, when
|
||||||
|
packet filtering is not desired and can have unexpected effects.
|
||||||
|
For example:
|
||||||
|
.Pp
|
||||||
|
.Dl set skip on lo0
|
||||||
|
.Pp
|
||||||
.It Ar set debug
|
.It Ar set debug
|
||||||
Set the debug
|
Set the debug
|
||||||
.Ar level
|
.Ar level
|
||||||
@ -548,7 +558,7 @@ Enforces a maximum MSS for matching TCP packets.
|
|||||||
.It Ar random-id
|
.It Ar random-id
|
||||||
Replaces the IP identification field with random values to compensate
|
Replaces the IP identification field with random values to compensate
|
||||||
for predictable values generated by many hosts.
|
for predictable values generated by many hosts.
|
||||||
This option only applies to outgoing packets that are not fragmented
|
This option only applies to packets that are not fragmented
|
||||||
after the optional fragment reassembly.
|
after the optional fragment reassembly.
|
||||||
.It Ar fragment reassemble
|
.It Ar fragment reassemble
|
||||||
Using
|
Using
|
||||||
@ -602,7 +612,7 @@ the firewall state, and expires before reaching the destination host.
|
|||||||
.Ar reassemble tcp
|
.Ar reassemble tcp
|
||||||
will raise the TTL of all packets back up to the highest value seen on
|
will raise the TTL of all packets back up to the highest value seen on
|
||||||
the connection.
|
the connection.
|
||||||
.It timeout modulation
|
.It timestamp modulation
|
||||||
Modern TCP stacks will send a timestamp on every TCP packet and echo
|
Modern TCP stacks will send a timestamp on every TCP packet and echo
|
||||||
the other endpoint's timestamp back to them.
|
the other endpoint's timestamp back to them.
|
||||||
Many operating systems will merely start the timestamp at zero when
|
Many operating systems will merely start the timestamp at zero when
|
||||||
@ -619,6 +629,24 @@ guessable base time.
|
|||||||
will cause
|
will cause
|
||||||
.Ar scrub
|
.Ar scrub
|
||||||
to modulate the TCP timestamps with a random number.
|
to modulate the TCP timestamps with a random number.
|
||||||
|
.It extended PAWS checks
|
||||||
|
There is a problem with TCP on long fat pipes, in that a packet might get
|
||||||
|
delayed for longer than it takes the connection to wrap its 32-bit sequence
|
||||||
|
space.
|
||||||
|
In such an occurrence, the old packet would be indistinguishable from a
|
||||||
|
new packet and would be accepted as such.
|
||||||
|
The solution to this is called PAWS: Protection Against Wrapped Sequence
|
||||||
|
numbers.
|
||||||
|
It protects against it by making sure the timestamp on each packet does
|
||||||
|
not go backwards.
|
||||||
|
.Ar reassemble tcp
|
||||||
|
also makes sure the timestamp on the packet does not go forward more
|
||||||
|
than the RFC allows.
|
||||||
|
By doing this,
|
||||||
|
.Xr pf 4
|
||||||
|
artificially extends the security of TCP sequence numbers by 10 to 18
|
||||||
|
bits when the host uses appropriately randomized timestamps, since a
|
||||||
|
blind attacker would have to guess the timestamp as well.
|
||||||
.El
|
.El
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
@ -626,6 +654,15 @@ For example,
|
|||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
scrub in on $ext_if all fragment reassemble
|
scrub in on $ext_if all fragment reassemble
|
||||||
.Ed
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Ar no
|
||||||
|
option prefixed to a scrub rule causes matching packets to remain unscrubbed,
|
||||||
|
much in the same way as
|
||||||
|
.Ar drop quick
|
||||||
|
works in the packet filter (see below).
|
||||||
|
This mechanism should be used when it is necessary to exclude specific packets
|
||||||
|
from broader scrub rules.
|
||||||
.Sh QUEUEING/ALTQ
|
.Sh QUEUEING/ALTQ
|
||||||
The ALTQ system is currently not available in the GENERIC kernel nor as
|
The ALTQ system is currently not available in the GENERIC kernel nor as
|
||||||
loadable modules.
|
loadable modules.
|
||||||
@ -673,6 +710,18 @@ assigned.
|
|||||||
mainly controls the time packets take to get sent out, while
|
mainly controls the time packets take to get sent out, while
|
||||||
.Ar bandwidth
|
.Ar bandwidth
|
||||||
has primarily effects on throughput.
|
has primarily effects on throughput.
|
||||||
|
.Ar cbq
|
||||||
|
achieves both partitioning and sharing of link bandwidth
|
||||||
|
by hierarchically structured classes.
|
||||||
|
Each class has its own
|
||||||
|
.Ar queue
|
||||||
|
and is assigned its share of
|
||||||
|
.Ar bandwidth .
|
||||||
|
A child class can borrow bandwidth from its parent class
|
||||||
|
as long as excess bandwidth is available
|
||||||
|
(see the option
|
||||||
|
.Ar borrow ,
|
||||||
|
below).
|
||||||
.It Ar priq
|
.It Ar priq
|
||||||
Priority Queueing.
|
Priority Queueing.
|
||||||
.Ar Queues
|
.Ar Queues
|
||||||
@ -706,6 +755,14 @@ assigned.
|
|||||||
mainly controls the time packets take to get sent out, while
|
mainly controls the time packets take to get sent out, while
|
||||||
.Ar bandwidth
|
.Ar bandwidth
|
||||||
has primarily effects on throughput.
|
has primarily effects on throughput.
|
||||||
|
.Ar hfsc
|
||||||
|
supports both link-sharing and guaranteed real-time services.
|
||||||
|
It employs a service curve based QoS model,
|
||||||
|
and its unique feature is an ability to decouple
|
||||||
|
.Ar delay
|
||||||
|
and
|
||||||
|
.Ar bandwidth
|
||||||
|
allocation.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The interfaces on which queueing should be activated are declared using
|
The interfaces on which queueing should be activated are declared using
|
||||||
@ -791,6 +848,7 @@ This value must not exceed the value of the parent
|
|||||||
.Ar queue
|
.Ar queue
|
||||||
and can be specified as an absolute value or a percentage of the parent
|
and can be specified as an absolute value or a percentage of the parent
|
||||||
queue's bandwidth.
|
queue's bandwidth.
|
||||||
|
If not specified, defaults to 100% of the parent queue's bandwidth.
|
||||||
The
|
The
|
||||||
.Ar priq
|
.Ar priq
|
||||||
scheduler does not support bandwidth specification.
|
scheduler does not support bandwidth specification.
|
||||||
@ -919,8 +977,8 @@ queue developers bandwidth 75% cbq(borrow)
|
|||||||
queue employees bandwidth 15%
|
queue employees bandwidth 15%
|
||||||
queue mail bandwidth 10% priority 0 cbq(borrow ecn)
|
queue mail bandwidth 10% priority 0 cbq(borrow ecn)
|
||||||
queue ssh bandwidth 20% cbq(borrow) { ssh_interactive, ssh_bulk }
|
queue ssh bandwidth 20% cbq(borrow) { ssh_interactive, ssh_bulk }
|
||||||
queue ssh_interactive priority 7
|
queue ssh_interactive bandwidth 50% priority 7 cbq(borrow)
|
||||||
queue ssh_bulk priority 0
|
queue ssh_bulk bandwidth 50% priority 0 cbq(borrow)
|
||||||
|
|
||||||
block return out on dc0 inet all queue std
|
block return out on dc0 inet all queue std
|
||||||
pass out on dc0 inet proto tcp from $developerhosts to any port 80 \e
|
pass out on dc0 inet proto tcp from $developerhosts to any port 80 \e
|
||||||
@ -944,8 +1002,8 @@ the packet filter for evaluation.
|
|||||||
.Pp
|
.Pp
|
||||||
Since translation occurs before filtering the filter
|
Since translation occurs before filtering the filter
|
||||||
engine will see packets as they look after any
|
engine will see packets as they look after any
|
||||||
addresses and ports have been translated. Filter rules
|
addresses and ports have been translated.
|
||||||
will therefore have to filter based on the translated
|
Filter rules will therefore have to filter based on the translated
|
||||||
address and port number.
|
address and port number.
|
||||||
Packets that match a translation rule are only automatically passed if
|
Packets that match a translation rule are only automatically passed if
|
||||||
the
|
the
|
||||||
@ -1107,10 +1165,11 @@ This causes a TCP RST to be returned for
|
|||||||
packets and an ICMP UNREACHABLE for UDP and other packets.
|
packets and an ICMP UNREACHABLE for UDP and other packets.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
Options returning packets have no effect if
|
Options returning ICMP packets currently have no effect if
|
||||||
.Xr pf 4
|
.Xr pf 4
|
||||||
operates on a
|
operates on a
|
||||||
.Xr bridge 4 .
|
.Xr bridge 4 ,
|
||||||
|
as the code to support this feature has not yet been implemented.
|
||||||
.It Ar pass
|
.It Ar pass
|
||||||
The packet is passed.
|
The packet is passed.
|
||||||
.El
|
.El
|
||||||
@ -1221,9 +1280,16 @@ addresses and ports.
|
|||||||
Addresses can be specified in CIDR notation (matching netblocks), as
|
Addresses can be specified in CIDR notation (matching netblocks), as
|
||||||
symbolic host names or interface names, or as any of the following keywords:
|
symbolic host names or interface names, or as any of the following keywords:
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -tag -width xxxxxxxxxxxx -compact
|
.Bl -tag -width xxxxxxxxxxxxxx -compact
|
||||||
.It Ar any
|
.It Ar any
|
||||||
Any address.
|
Any address.
|
||||||
|
.It Ar route <label>
|
||||||
|
Any address whose associated route has label
|
||||||
|
.Ar <label> .
|
||||||
|
See
|
||||||
|
.Xr route 4
|
||||||
|
and
|
||||||
|
.Xr route 8 .
|
||||||
.It Ar no-route
|
.It Ar no-route
|
||||||
Any address which is not currently routable.
|
Any address which is not currently routable.
|
||||||
.It Ar <table>
|
.It Ar <table>
|
||||||
@ -1317,6 +1383,7 @@ pass in proto tcp from any to any port 25
|
|||||||
pass in proto tcp from 10.0.0.0/8 port > 1024 \e
|
pass in proto tcp from 10.0.0.0/8 port > 1024 \e
|
||||||
to ! 10.1.2.3 port != ssh
|
to ! 10.1.2.3 port != ssh
|
||||||
pass in proto tcp from any os "OpenBSD" flags S/SA
|
pass in proto tcp from any os "OpenBSD" flags S/SA
|
||||||
|
pass in proto tcp from route "DTAG"
|
||||||
.Ed
|
.Ed
|
||||||
.It Ar all
|
.It Ar all
|
||||||
This is equivalent to "from any to any".
|
This is equivalent to "from any to any".
|
||||||
@ -1412,9 +1479,18 @@ All of SYN, FIN, RST and ACK must be unset.
|
|||||||
.It Ar icmp6-type <type> code <code>
|
.It Ar icmp6-type <type> code <code>
|
||||||
This rule only applies to ICMP or ICMPv6 packets with the specified type
|
This rule only applies to ICMP or ICMPv6 packets with the specified type
|
||||||
and code.
|
and code.
|
||||||
|
Text names for ICMP types and codes are listed in
|
||||||
|
.Xr icmp 4
|
||||||
|
and
|
||||||
|
.Xr icmp6 4 .
|
||||||
This parameter is only valid for rules that cover protocols ICMP or
|
This parameter is only valid for rules that cover protocols ICMP or
|
||||||
ICMP6.
|
ICMP6.
|
||||||
The protocol and the ICMP type indicator (icmp-type or icmp6-type)
|
The protocol and the ICMP type indicator
|
||||||
|
.Po
|
||||||
|
.Ar icmp-type
|
||||||
|
or
|
||||||
|
.Ar icmp6-type
|
||||||
|
.Pc
|
||||||
must match.
|
must match.
|
||||||
.It Ar allow-opts
|
.It Ar allow-opts
|
||||||
By default, packets which contain IP options are blocked.
|
By default, packets which contain IP options are blocked.
|
||||||
@ -1520,7 +1596,7 @@ or
|
|||||||
rules in addition to filter rules.
|
rules in addition to filter rules.
|
||||||
Tags take the same macros as labels (see above).
|
Tags take the same macros as labels (see above).
|
||||||
.It Ar tagged <string>
|
.It Ar tagged <string>
|
||||||
Used with filter rules to specify that packets must already
|
Used with filter or translation rules to specify that packets must already
|
||||||
be tagged with the given tag in order to match the rule.
|
be tagged with the given tag in order to match the rule.
|
||||||
Inverse tag matching can also be done
|
Inverse tag matching can also be done
|
||||||
by specifying the
|
by specifying the
|
||||||
@ -1528,6 +1604,15 @@ by specifying the
|
|||||||
operator before the
|
operator before the
|
||||||
.Ar tagged
|
.Ar tagged
|
||||||
keyword.
|
keyword.
|
||||||
|
.It Ar probability <number>
|
||||||
|
A probability attribute can be attached to a rule, with a value set between
|
||||||
|
0 and 1, bounds not included.
|
||||||
|
In that case, the rule will be honoured using the given probability value
|
||||||
|
only.
|
||||||
|
For example, the following rule will drop 20% of incoming ICMP packets:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
block in proto icmp probability 20%
|
||||||
|
.Ed
|
||||||
.El
|
.El
|
||||||
.Sh ROUTING
|
.Sh ROUTING
|
||||||
If a packet matches a rule with a route option set, the packet filter will
|
If a packet matches a rule with a route option set, the packet filter will
|
||||||
@ -1558,7 +1643,7 @@ option is similar to
|
|||||||
but routes packets that pass in the opposite direction (replies) to the
|
but routes packets that pass in the opposite direction (replies) to the
|
||||||
specified interface.
|
specified interface.
|
||||||
Opposite direction is only defined in the context of a state entry, and
|
Opposite direction is only defined in the context of a state entry, and
|
||||||
.Ar route-to
|
.Ar reply-to
|
||||||
is useful only in rules that create state.
|
is useful only in rules that create state.
|
||||||
It can be used on systems with multiple external connections to
|
It can be used on systems with multiple external connections to
|
||||||
route all outgoing packets of a connection through the interface
|
route all outgoing packets of a connection through the interface
|
||||||
@ -1875,32 +1960,96 @@ Prevent state changes for states created by this rule from appearing on the
|
|||||||
interface.
|
interface.
|
||||||
.It Ar <timeout> <seconds>
|
.It Ar <timeout> <seconds>
|
||||||
Changes the timeout values used for states created by this rule.
|
Changes the timeout values used for states created by this rule.
|
||||||
.Pp
|
|
||||||
When the
|
|
||||||
.Ar source-track
|
|
||||||
keyword is specified, the number of states per source IP is tracked.
|
|
||||||
The following limits can be set:
|
|
||||||
.Pp
|
|
||||||
.Bl -tag -width xxxx -compact
|
|
||||||
.It Ar max-src-nodes
|
|
||||||
Limits the maximum number of source addresses which can simultaneously
|
|
||||||
have state table entries.
|
|
||||||
.It Ar max-src-states
|
|
||||||
Limits the maximum number of simultaneous state entries that a single
|
|
||||||
source address can create with this rule.
|
|
||||||
.El
|
|
||||||
For a list of all valid timeout names, see
|
For a list of all valid timeout names, see
|
||||||
.Sx OPTIONS
|
.Sx OPTIONS
|
||||||
above.
|
above.
|
||||||
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
Multiple options can be specified, separated by commas:
|
Multiple options can be specified, separated by commas:
|
||||||
.Bd -literal
|
.Bd -literal -offset indent
|
||||||
pass in proto tcp from any to any \e
|
pass in proto tcp from any to any \e
|
||||||
port www flags S/SA keep state \e
|
port www flags S/SA keep state \e
|
||||||
(max 100, source-track rule, max-src-nodes 75, \e
|
(max 100, source-track rule, max-src-nodes 75, \e
|
||||||
max-src-states 3, tcp.established 60, tcp.closing 5)
|
max-src-states 3, tcp.established 60, tcp.closing 5)
|
||||||
.Ed
|
.Ed
|
||||||
|
.Pp
|
||||||
|
When the
|
||||||
|
.Ar source-track
|
||||||
|
keyword is specified, the number of states per source IP is tracked.
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width xxxx -compact
|
||||||
|
.It Ar source-track rule
|
||||||
|
The maximum number of states created by this rule is limited by the rule's
|
||||||
|
.Ar max-src-nodes
|
||||||
|
and
|
||||||
|
.Ar max-src-state
|
||||||
|
options.
|
||||||
|
Only state entries created by this particular rule count toward the rule's
|
||||||
|
limits.
|
||||||
|
.It Ar source-track global
|
||||||
|
The number of states created by all rules that use this option is limited.
|
||||||
|
Each rule can specify different
|
||||||
|
.Ar max-src-nodes
|
||||||
|
and
|
||||||
|
.Ar max-src-states
|
||||||
|
options, however state entries created by any participating rule count towards
|
||||||
|
each individual rule's limits.
|
||||||
.El
|
.El
|
||||||
|
.Pp
|
||||||
|
The following limits can be set:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width xxxx -compact
|
||||||
|
.It Ar max-src-nodes <number>
|
||||||
|
Limits the maximum number of source addresses which can simultaneously
|
||||||
|
have state table entries.
|
||||||
|
.It Ar max-src-states <number>
|
||||||
|
Limits the maximum number of simultaneous state entries that a single
|
||||||
|
source address can create with this rule.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
For stateful TCP connections, limits on established connections (connections
|
||||||
|
which have completed the TCP 3-way handshake) can also be enforced
|
||||||
|
per source IP.
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width xxxx -compact
|
||||||
|
.It Ar max-src-conn <number>
|
||||||
|
Limits the maximum number of simultaneous TCP connections which have
|
||||||
|
completed the 3-way handshake that a single host can make.
|
||||||
|
.It Ar max-src-conn-rate <number> / <seconds>
|
||||||
|
Limit the rate of new connections over a time interval.
|
||||||
|
The connection rate is an approximation calculated as a moving average.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Because the 3-way handshake ensures that the source address is not being
|
||||||
|
spoofed, more aggressive action can be taken based on these limits.
|
||||||
|
With the
|
||||||
|
.Ar overload <table>
|
||||||
|
state option, source IP addresses which hit either of the limits on
|
||||||
|
established connections will be added to the named table.
|
||||||
|
This table can be used in the ruleset to block further activity from
|
||||||
|
the offending host, redirect it to a tarpit process, or restrict its
|
||||||
|
bandwidth.
|
||||||
|
.Pp
|
||||||
|
The optional
|
||||||
|
.Ar flush
|
||||||
|
keyword kills all states created by the matching rule which originate
|
||||||
|
from the host which exceeds these limits.
|
||||||
|
The
|
||||||
|
.Ar global
|
||||||
|
modifier to the flush command kills all states originating from the
|
||||||
|
offending host, regardless of which rule created the state.
|
||||||
|
.Pp
|
||||||
|
For example, the following rules will protect the webserver against
|
||||||
|
hosts making more than 100 connections in 10 seconds.
|
||||||
|
Any host which connects faster than this rate will have its address added
|
||||||
|
to the <bad_hosts> table and have all states originating from it flushed.
|
||||||
|
Any new packets arriving from this host will be dropped unconditionally
|
||||||
|
by the block rule.
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
block quick from <bad_hosts>
|
||||||
|
pass in on $ext_if proto tcp to $webserver port www flags S/SA keep state \e
|
||||||
|
(max-src-conn-rate 100/10, overload <bad_hosts> flush global)
|
||||||
|
.Ed
|
||||||
.Sh OPERATING SYSTEM FINGERPRINTING
|
.Sh OPERATING SYSTEM FINGERPRINTING
|
||||||
Passive OS Fingerprinting is a mechanism to inspect nuances of a TCP
|
Passive OS Fingerprinting is a mechanism to inspect nuances of a TCP
|
||||||
connection's initial SYN packet and guess at the host's operating system.
|
connection's initial SYN packet and guess at the host's operating system.
|
||||||
@ -1911,7 +2060,7 @@ upon.
|
|||||||
.Pp
|
.Pp
|
||||||
The fingerprints may be specified by operating system class, by
|
The fingerprints may be specified by operating system class, by
|
||||||
version, or by subtype/patchlevel.
|
version, or by subtype/patchlevel.
|
||||||
The class of an operating system is typically the vender or genre
|
The class of an operating system is typically the vendor or genre
|
||||||
and would be OpenBSD for the
|
and would be OpenBSD for the
|
||||||
.Xr pf 4
|
.Xr pf 4
|
||||||
firewall itself.
|
firewall itself.
|
||||||
@ -2076,84 +2225,87 @@ The timeout value can also be adjusted.
|
|||||||
.Pp
|
.Pp
|
||||||
Currently, only IPv4 fragments are supported and IPv6 fragments
|
Currently, only IPv4 fragments are supported and IPv6 fragments
|
||||||
are blocked unconditionally.
|
are blocked unconditionally.
|
||||||
.Sh ANCHORS AND NAMED RULESETS
|
.Sh ANCHORS
|
||||||
Besides the main ruleset,
|
Besides the main ruleset,
|
||||||
.Xr pfctl 8
|
.Xr pfctl 8
|
||||||
can load named rulesets into
|
can load rulesets into
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
attachment points.
|
attachment points.
|
||||||
An
|
An
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
contains a list of named rulesets.
|
is a container that can hold rules, address tables, and other anchors.
|
||||||
|
.Pp
|
||||||
An
|
An
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
has a name which specifies where
|
has a name which specifies the path where
|
||||||
.Xr pfctl 8
|
.Xr pfctl 8
|
||||||
can be used to attach sub-rulesets.
|
can be used to access the anchor to perform operations on it, such as
|
||||||
A named ruleset contains filter and translation rules, like the
|
attaching child anchors to it or loading rules into it.
|
||||||
main ruleset.
|
Anchors may be nested, with components separated by
|
||||||
The main ruleset can reference
|
.Sq /
|
||||||
|
characters, similar to how file system hierarchies are laid out.
|
||||||
|
The main ruleset is actually the default anchor, so filter and
|
||||||
|
translation rules, for example, may also be contained in any anchor.
|
||||||
|
.Pp
|
||||||
|
An anchor can reference another
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
attachment points
|
attachment point
|
||||||
using the following kinds
|
using the following kinds
|
||||||
of rules:
|
of rules:
|
||||||
.Bl -tag -width xxxx
|
.Bl -tag -width xxxx
|
||||||
.It Ar nat-anchor <name>
|
.It Ar nat-anchor <name>
|
||||||
Evaluates the
|
Evaluates the
|
||||||
.Ar nat
|
.Ar nat
|
||||||
rules of all named rulesets in the specified
|
rules in the specified
|
||||||
.Ar anchor .
|
.Ar anchor .
|
||||||
.It Ar rdr-anchor <name>
|
.It Ar rdr-anchor <name>
|
||||||
Evaluates the
|
Evaluates the
|
||||||
.Ar rdr
|
.Ar rdr
|
||||||
rules of all named rulesets in the specified
|
rules in the specified
|
||||||
.Ar anchor .
|
.Ar anchor .
|
||||||
.It Ar binat-anchor <name>
|
.It Ar binat-anchor <name>
|
||||||
Evaluates the
|
Evaluates the
|
||||||
.Ar binat
|
.Ar binat
|
||||||
rules of all named rulesets in the specified
|
rules in the specified
|
||||||
.Ar anchor .
|
.Ar anchor .
|
||||||
.It Ar anchor <name>
|
.It Ar anchor <name>
|
||||||
Evaluates the filter rules of all named rulesets in the specified
|
Evaluates the filter rules in the specified
|
||||||
.Ar anchor .
|
.Ar anchor .
|
||||||
.It Ar load anchor <name>:<ruleset> from <file>
|
.It Ar load anchor <name> from <file>
|
||||||
Loads the rules from the specified file into the named
|
Loads the rules from the specified file into the
|
||||||
ruleset
|
anchor
|
||||||
.Ar <ruleset>
|
.Ar name .
|
||||||
attached to the anchor
|
|
||||||
.Ar <name> .
|
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
When evaluation of the main ruleset reaches an
|
When evaluation of the main ruleset reaches an
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
rule,
|
rule,
|
||||||
.Xr pf 4
|
.Xr pf 4
|
||||||
will proceed to evaluate all rules specified in the
|
will proceed to evaluate all rules specified in that anchor.
|
||||||
named rulesets attached to that
|
|
||||||
.Ar anchor .
|
|
||||||
.Pp
|
.Pp
|
||||||
Matching filter rules in named rulesets with the
|
Matching filter and translation rules in anchors with the
|
||||||
.Ar quick
|
.Ar quick
|
||||||
option and matching translation rules are final and abort the
|
option are final and abort the evaluation of the rules in other
|
||||||
evaluation of both the rules in the
|
anchors
|
||||||
.Ar anchor
|
|
||||||
and the main ruleset.
|
and the main ruleset.
|
||||||
.Pp
|
.Pp
|
||||||
Only the main ruleset can contain
|
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
rules.
|
rules are evaluated relative to the anchor in which they are contained.
|
||||||
.Pp
|
For example, all
|
||||||
When an
|
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
contains more than one named ruleset, they are evaluated
|
rules specified in the main ruleset will reference anchor
|
||||||
in the alphabetical order of their names.
|
attachment points underneath the main ruleset, and
|
||||||
|
.Ar anchor
|
||||||
|
rules specified in a file loaded from a
|
||||||
|
.Ar load anchor
|
||||||
|
rule will be attached under that anchor point.
|
||||||
.Pp
|
.Pp
|
||||||
Rules may contain
|
Rules may be contained in
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
attachment points which do not contain any rules when the main ruleset
|
attachment points which do not contain any rules when the main ruleset
|
||||||
is loaded, and later such named rulesets can be manipulated through
|
is loaded, and later such anchors can be manipulated through
|
||||||
.Xr pfctl 8
|
.Xr pfctl 8
|
||||||
without reloading the main ruleset.
|
without reloading the main ruleset or other anchors.
|
||||||
For example,
|
For example,
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
ext_if = \&"kue0\&"
|
ext_if = \&"kue0\&"
|
||||||
@ -2165,27 +2317,27 @@ pass in on $ext_if proto tcp from any \e
|
|||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
blocks all packets on the external interface by default, then evaluates
|
blocks all packets on the external interface by default, then evaluates
|
||||||
all rulesets in the
|
all rules in the
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
named "spam", and finally passes all outgoing connections and
|
named "spam", and finally passes all outgoing connections and
|
||||||
incoming connections to port 25.
|
incoming connections to port 25.
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
# echo \&"block in quick from 1.2.3.4 to any\&" \&| \e
|
# echo \&"block in quick from 1.2.3.4 to any\&" \&| \e
|
||||||
pfctl -a spam:manual -f -
|
pfctl -a spam -f -
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
loads a single ruleset containing a single rule into the
|
This loads a single rule into the
|
||||||
.Ar anchor ,
|
.Ar anchor ,
|
||||||
which blocks all packets from a specific address.
|
which blocks all packets from a specific address.
|
||||||
.Pp
|
.Pp
|
||||||
The named ruleset can also be populated by adding a
|
The anchor can also be populated by adding a
|
||||||
.Ar load anchor
|
.Ar load anchor
|
||||||
rule after the
|
rule after the
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
rule:
|
rule:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
anchor spam
|
anchor spam
|
||||||
load anchor spam:manual from "/etc/pf-spam.conf"
|
load anchor spam from "/etc/pf-spam.conf"
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
When
|
When
|
||||||
@ -2194,7 +2346,7 @@ loads
|
|||||||
.Nm pf.conf ,
|
.Nm pf.conf ,
|
||||||
it will also load all the rules from the file
|
it will also load all the rules from the file
|
||||||
.Pa /etc/pf-spam.conf
|
.Pa /etc/pf-spam.conf
|
||||||
into the named ruleset.
|
into the anchor.
|
||||||
.Pp
|
.Pp
|
||||||
Optionally,
|
Optionally,
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
@ -2205,7 +2357,7 @@ using the same syntax as filter rules.
|
|||||||
When parameters are used, the
|
When parameters are used, the
|
||||||
.Ar anchor
|
.Ar anchor
|
||||||
rule is only evaluated for matching packets.
|
rule is only evaluated for matching packets.
|
||||||
This allows conditional evaluation of named rulesets, like:
|
This allows conditional evaluation of anchors, like:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
block on $ext_if all
|
block on $ext_if all
|
||||||
anchor spam proto tcp from any to any port smtp
|
anchor spam proto tcp from any to any port smtp
|
||||||
@ -2221,10 +2373,56 @@ packets with destination port 25.
|
|||||||
Hence,
|
Hence,
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
# echo \&"block in quick from 1.2.3.4 to any" \&| \e
|
# echo \&"block in quick from 1.2.3.4 to any" \&| \e
|
||||||
pfctl -a spam:manual -f -
|
pfctl -a spam -f -
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
will only block connections from 1.2.3.4 to port 25.
|
will only block connections from 1.2.3.4 to port 25.
|
||||||
|
.Pp
|
||||||
|
Anchors may end with the asterisk
|
||||||
|
.Pq Sq *
|
||||||
|
character, which signifies that all anchors attached at that point
|
||||||
|
should be evaluated in the alphabetical ordering of their anchor name.
|
||||||
|
For example,
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
anchor "spam/*"
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
will evaluate each rule in each anchor attached to the
|
||||||
|
.Li spam
|
||||||
|
anchor.
|
||||||
|
Note that it will only evaluate anchors that are directly attached to the
|
||||||
|
.Li spam
|
||||||
|
anchor, and will not descend to evaluate anchors recursively.
|
||||||
|
.Pp
|
||||||
|
Since anchors are evaluated relative to the anchor in which they are
|
||||||
|
contained, there is a mechanism for accessing the parent and ancestor
|
||||||
|
anchors of a given anchor.
|
||||||
|
Similar to file system path name resolution, if the sequence
|
||||||
|
.Dq ..
|
||||||
|
appears as an anchor path component, the parent anchor of the current
|
||||||
|
anchor in the path evaluation at that point will become the new current
|
||||||
|
anchor.
|
||||||
|
As an example, consider the following:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
# echo ' anchor "spam/allowed" ' | pfctl -f -
|
||||||
|
# echo -e ' anchor "../banned" \en pass' | \e
|
||||||
|
pfctl -a spam/allowed -f -
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Evaluation of the main ruleset will lead into the
|
||||||
|
.Li spam/allowed
|
||||||
|
anchor, which will evaluate the rules in the
|
||||||
|
.Li spam/banned
|
||||||
|
anchor, if any, before finally evaluating the
|
||||||
|
.Ar pass
|
||||||
|
rule.
|
||||||
|
.Pp
|
||||||
|
Since the parser specification for anchor names is a string, any
|
||||||
|
reference to an anchor name containing solidus
|
||||||
|
.Pq Sq /
|
||||||
|
characters will require double quote
|
||||||
|
.Pq Sq \&"
|
||||||
|
characters around the anchor name.
|
||||||
.Sh TRANSLATION EXAMPLES
|
.Sh TRANSLATION EXAMPLES
|
||||||
This example maps incoming requests on port 80 to port 8080, on
|
This example maps incoming requests on port 80 to port 8080, on
|
||||||
which a daemon is running (because, for example, it is not run as root,
|
which a daemon is running (because, for example, it is not run as root,
|
||||||
@ -2301,7 +2499,7 @@ nat on $ext_if inet proto udp from any port = isakmp to any -> ($ext_if) \e
|
|||||||
# Translate outgoing packets' source address (any protocol).
|
# Translate outgoing packets' source address (any protocol).
|
||||||
# Translate incoming packets' destination address to an internal machine
|
# Translate incoming packets' destination address to an internal machine
|
||||||
# (bidirectional).
|
# (bidirectional).
|
||||||
binat on $ext_if from 10.1.2.150 to any -> ($ext_if)
|
binat on $ext_if from 10.1.2.150 to any -> $ext_if
|
||||||
|
|
||||||
# RDR
|
# RDR
|
||||||
# Translate incoming packets' destination addresses.
|
# Translate incoming packets' destination addresses.
|
||||||
@ -2415,7 +2613,7 @@ pass in on $wifi_if from any to any keep state
|
|||||||
|
|
||||||
block out on $ext_if from any to any
|
block out on $ext_if from any to any
|
||||||
pass out quick on $ext_if tagged INTNET keep state
|
pass out quick on $ext_if tagged INTNET keep state
|
||||||
pass out on $ext_if from any to any port 80 keep state
|
pass out on $ext_if proto tcp from any to any port 80 keep state
|
||||||
|
|
||||||
# tag incoming packets as they are redirected to spamd(8). use the tag
|
# tag incoming packets as they are redirected to spamd(8). use the tag
|
||||||
# to pass those packets through the packet filter.
|
# to pass those packets through the packet filter.
|
||||||
@ -2442,7 +2640,7 @@ option = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] |
|
|||||||
[ "limit" ( limit-item | "{" limit-list "}" ) ] |
|
[ "limit" ( limit-item | "{" limit-list "}" ) ] |
|
||||||
[ "loginterface" ( interface-name | "none" ) ] |
|
[ "loginterface" ( interface-name | "none" ) ] |
|
||||||
[ "block-policy" ( "drop" | "return" ) ] |
|
[ "block-policy" ( "drop" | "return" ) ] |
|
||||||
[ "state-policy" ( "if-bound" | "group-bound" |
|
[ "state-policy" ( "if-bound" | "group-bound" |
|
||||||
"floating" ) ]
|
"floating" ) ]
|
||||||
[ "require-order" ( "yes" | "no" ) ]
|
[ "require-order" ( "yes" | "no" ) ]
|
||||||
[ "fingerprints" filename ] |
|
[ "fingerprints" filename ] |
|
||||||
@ -2461,21 +2659,22 @@ filteropt = user | group | flags | icmp-type | icmp6-type | tos |
|
|||||||
"max-mss" number | "random-id" | "reassemble tcp" |
|
"max-mss" number | "random-id" | "reassemble tcp" |
|
||||||
fragmentation | "allow-opts" |
|
fragmentation | "allow-opts" |
|
||||||
"label" string | "tag" string | [ ! ] "tagged" string
|
"label" string | "tag" string | [ ! ] "tagged" string
|
||||||
"queue" ( string | "(" string [ [ "," ] string ] ")" )
|
"queue" ( string | "(" string [ [ "," ] string ] ")" ) |
|
||||||
|
"probability" number"%"
|
||||||
|
|
||||||
nat-rule = [ "no" ] "nat" [ "pass" ] [ "on" ifspec ] [ af ]
|
nat-rule = [ "no" ] "nat" [ "pass" ] [ "on" ifspec ] [ af ]
|
||||||
[ protospec ] hosts [ "tag" string ]
|
[ protospec ] hosts [ "tag" string ] [ "tagged" string ]
|
||||||
[ "->" ( redirhost | "{" redirhost-list "}" )
|
[ "->" ( redirhost | "{" redirhost-list "}" )
|
||||||
[ portspec ] [ pooltype ] [ "static-port" ] ]
|
[ portspec ] [ pooltype ] [ "static-port" ] ]
|
||||||
|
|
||||||
binat-rule = [ "no" ] "binat" [ "pass" ] [ "on" interface-name ]
|
binat-rule = [ "no" ] "binat" [ "pass" ] [ "on" interface-name ]
|
||||||
[ af ] [ "proto" ( proto-name | proto-number ) ]
|
[ af ] [ "proto" ( proto-name | proto-number ) ]
|
||||||
"from" address [ "/" mask-bits ] "to" ipspec
|
"from" address [ "/" mask-bits ] "to" ipspec
|
||||||
[ "tag" string ]
|
[ "tag" string ] [ "tagged" string ]
|
||||||
[ "->" address [ "/" mask-bits ] ]
|
[ "->" address [ "/" mask-bits ] ]
|
||||||
|
|
||||||
rdr-rule = [ "no" ] "rdr" [ "pass" ] [ "on" ifspec ] [ af ]
|
rdr-rule = [ "no" ] "rdr" [ "pass" ] [ "on" ifspec ] [ af ]
|
||||||
[ protospec ] hosts [ "tag" string ]
|
[ protospec ] hosts [ "tag" string ] [ "tagged" string ]
|
||||||
[ "->" ( redirhost | "{" redirhost-list "}" )
|
[ "->" ( redirhost | "{" redirhost-list "}" )
|
||||||
[ portspec ] [ pooltype ] ]
|
[ portspec ] [ pooltype ] ]
|
||||||
|
|
||||||
@ -2503,7 +2702,7 @@ anchor-rule = "anchor" string [ ( "in" | "out" ) ] [ "on" ifspec ]
|
|||||||
trans-anchors = ( "nat-anchor" | "rdr-anchor" | "binat-anchor" ) string
|
trans-anchors = ( "nat-anchor" | "rdr-anchor" | "binat-anchor" ) string
|
||||||
[ "on" ifspec ] [ af ] [ "proto" ] [ protospec ] [ hosts ]
|
[ "on" ifspec ] [ af ] [ "proto" ] [ protospec ] [ hosts ]
|
||||||
|
|
||||||
load-anchor = "load anchor" anchorname:rulesetname "from" filename
|
load-anchor = "load anchor" string "from" filename
|
||||||
|
|
||||||
queueopts-list = queueopts-list queueopts | queueopts
|
queueopts-list = queueopts-list queueopts | queueopts
|
||||||
queueopts = [ "bandwidth" bandwidth-spec ] |
|
queueopts = [ "bandwidth" bandwidth-spec ] |
|
||||||
@ -2512,7 +2711,7 @@ queueopts = [ "bandwidth" bandwidth-spec ] |
|
|||||||
schedulers = ( cbq-def | priq-def | hfsc-def )
|
schedulers = ( cbq-def | priq-def | hfsc-def )
|
||||||
bandwidth-spec = "number" ( "b" | "Kb" | "Mb" | "Gb" | "%" )
|
bandwidth-spec = "number" ( "b" | "Kb" | "Mb" | "Gb" | "%" )
|
||||||
|
|
||||||
action = "pass" | "block" [ return ] | "scrub"
|
action = "pass" | "block" [ return ] | [ "no" ] "scrub"
|
||||||
return = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] |
|
return = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] |
|
||||||
"return-icmp" [ "(" icmpcode ["," icmp6code ] ")" ] |
|
"return-icmp" [ "(" icmpcode ["," icmp6code ] ")" ] |
|
||||||
"return-icmp6" [ "(" icmp6code ")" ]
|
"return-icmp6" [ "(" icmp6code ")" ]
|
||||||
@ -2533,9 +2732,9 @@ proto-list = ( proto-name | proto-number ) [ [ "," ] proto-list ]
|
|||||||
|
|
||||||
hosts = "all" |
|
hosts = "all" |
|
||||||
"from" ( "any" | "no-route" | "self" | host |
|
"from" ( "any" | "no-route" | "self" | host |
|
||||||
"{" host-list "}" ) [ port ] [ os ]
|
"{" host-list "}" | "route" string ) [ port ] [ os ]
|
||||||
"to" ( "any" | "no-route" | "self" | host |
|
"to" ( "any" | "no-route" | "self" | host |
|
||||||
"{" host-list "}" ) [ port ]
|
"{" host-list "}" | "route" string ) [ port ]
|
||||||
|
|
||||||
ipspec = "any" | host | "{" host-list "}"
|
ipspec = "any" | host | "{" host-list "}"
|
||||||
host = [ "!" ] ( address [ "/" mask-bits ] | "<" string ">" )
|
host = [ "!" ] ( address [ "/" mask-bits ] | "<" string ">" )
|
||||||
@ -2577,7 +2776,10 @@ tos = "tos" ( "lowdelay" | "throughput" | "reliability" |
|
|||||||
state-opts = state-opt [ [ "," ] state-opts ]
|
state-opts = state-opt [ [ "," ] state-opts ]
|
||||||
state-opt = ( "max" number | "no-sync" | timeout |
|
state-opt = ( "max" number | "no-sync" | timeout |
|
||||||
"source-track" [ ( "rule" | "global" ) ] |
|
"source-track" [ ( "rule" | "global" ) ] |
|
||||||
"max-src-nodes" number | "max-src-states" number |
|
"max-src-nodes" number | "max-src-states" number |
|
||||||
|
"max-src-conn" number |
|
||||||
|
"max-src-conn-rate" number "/" number |
|
||||||
|
"overload" "<" string ">" [ "flush" ] |
|
||||||
"if-bound" | "group-bound" | "floating" )
|
"if-bound" | "group-bound" | "floating" )
|
||||||
|
|
||||||
fragmentation = [ "fragment reassemble" | "fragment crop" |
|
fragmentation = [ "fragment reassemble" | "fragment crop" |
|
||||||
@ -2657,6 +2859,7 @@ deadlock.
|
|||||||
.Xr ip6 4 ,
|
.Xr ip6 4 ,
|
||||||
.Xr pf 4 ,
|
.Xr pf 4 ,
|
||||||
.Xr pfsync 4 ,
|
.Xr pfsync 4 ,
|
||||||
|
.Xr route 4 ,
|
||||||
.Xr tcp 4 ,
|
.Xr tcp 4 ,
|
||||||
.Xr udp 4 ,
|
.Xr udp 4 ,
|
||||||
.Xr hosts 5 ,
|
.Xr hosts 5 ,
|
||||||
@ -2665,7 +2868,8 @@ deadlock.
|
|||||||
.Xr services 5 ,
|
.Xr services 5 ,
|
||||||
.Xr ftp-proxy 8 ,
|
.Xr ftp-proxy 8 ,
|
||||||
.Xr pfctl 8 ,
|
.Xr pfctl 8 ,
|
||||||
.Xr pflogd 8
|
.Xr pflogd 8 ,
|
||||||
|
.Xr route 8
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
.\" $OpenBSD: pfsync.4,v 1.16 2004/03/22 21:04:36 jmc Exp $
|
.\" $OpenBSD: pfsync.4,v 1.22 2005/02/24 15:53:17 jmc Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2002 Michael Shalayeff
|
.\" Copyright (c) 2002 Michael Shalayeff
|
||||||
|
.\" Copyright (c) 2003-2004 Ryan McBride
|
||||||
.\" All rights reserved.
|
.\" All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
@ -30,7 +31,7 @@
|
|||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm pfsync
|
.Nm pfsync
|
||||||
.Nd packet filter states table logging interface
|
.Nd packet filter state table logging interface
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Cd "device pfsync"
|
.Cd "device pfsync"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
@ -71,20 +72,20 @@ state into one message where possible.
|
|||||||
The maximum number of times this can be done before the update is sent out
|
The maximum number of times this can be done before the update is sent out
|
||||||
is controlled by the
|
is controlled by the
|
||||||
.Ar maxupd
|
.Ar maxupd
|
||||||
to ifconfig.
|
parameter to ifconfig
|
||||||
(see
|
(see
|
||||||
.Xr ifconfig 8
|
.Xr ifconfig 8
|
||||||
and the example below for more details)
|
and the example below for more details).
|
||||||
.Pp
|
.Pp
|
||||||
Each packet retrieved on this interface has a header associated
|
Each packet retrieved on this interface has a header associated
|
||||||
with it of length
|
with it of length
|
||||||
.Dv PFSYNC_HDRLEN .
|
.Dv PFSYNC_HDRLEN .
|
||||||
The header indicates the version of the protocol, address family,
|
The header indicates the version of the protocol, address family,
|
||||||
action taken on the following states and the number of state
|
action taken on the following states, and the number of state
|
||||||
table entries attached in this packet.
|
table entries attached in this packet.
|
||||||
This structure, defined in
|
This structure is defined in
|
||||||
.Aq Pa net/if_pfsync.h
|
.Aq Pa net/if_pfsync.h
|
||||||
looks like:
|
as:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
struct pfsync_header {
|
struct pfsync_header {
|
||||||
u_int8_t version;
|
u_int8_t version;
|
||||||
@ -98,21 +99,35 @@ States can be synchronised between two or more firewalls using this
|
|||||||
interface, by specifying a synchronisation interface using
|
interface, by specifying a synchronisation interface using
|
||||||
.Xr ifconfig 8 .
|
.Xr ifconfig 8 .
|
||||||
For example, the following command sets fxp0 as the synchronisation
|
For example, the following command sets fxp0 as the synchronisation
|
||||||
interface.
|
interface:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
# ifconfig pfsync0 syncif fxp0
|
# ifconfig pfsync0 syncdev fxp0
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
State change messages are sent out on the synchronisation
|
By default, state change messages are sent out on the synchronisation
|
||||||
interface using IP multicast packets.
|
interface using IP multicast packets.
|
||||||
The protocol is IP protocol 240, PFSYNC, and the multicast group
|
The protocol is IP protocol 240, PFSYNC, and the multicast group
|
||||||
used is 224.0.0.240.
|
used is 224.0.0.240.
|
||||||
|
When a peer address is specified using the
|
||||||
|
.Ic syncpeer
|
||||||
|
keyword, the peer address is used as a destination for the pfsync traffic,
|
||||||
|
and the traffic can then be protected using
|
||||||
|
.Xr ipsec 4 .
|
||||||
|
In such a configuration, the syncdev should be set to the
|
||||||
|
.Xr enc 4
|
||||||
|
interface, as this is where the traffic arrives when it is decapsulated,
|
||||||
|
e.g.:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
# ifconfig pfsync0 syncpeer 10.0.0.2 syncdev enc0
|
||||||
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
It is important that the synchronisation interface be on a trusted
|
It is important that the pfsync traffic be well secured
|
||||||
network as there is no authentication on the protocol and it would
|
as there is no authentication on the protocol and it would
|
||||||
be trivial to spoof packets which create states, bypassing the pf ruleset.
|
be trivial to spoof packets which create states, bypassing the pf ruleset.
|
||||||
Ideally, this is a network dedicated to pfsync messages,
|
Either run the pfsync protocol on a trusted network \- ideally a network
|
||||||
i.e. a crossover cable between two firewalls.
|
dedicated to pfsync messages such as a crossover cable between two firewalls,
|
||||||
|
or specify a peer address and protect the traffic with
|
||||||
|
.Xr ipsec 4 .
|
||||||
.Pp
|
.Pp
|
||||||
.\" XXX: not yet!
|
.\" XXX: not yet!
|
||||||
.\" There is a one-to-one correspondence between packets seen by
|
.\" There is a one-to-one correspondence between packets seen by
|
||||||
@ -139,8 +154,8 @@ is shut down, the second firewall takes over automatically.
|
|||||||
Both firewalls in this example have three
|
Both firewalls in this example have three
|
||||||
.Xr sis 4
|
.Xr sis 4
|
||||||
interfaces.
|
interfaces.
|
||||||
sis0 is the external interface, on the 10.0.0.0/24 subnet, sis1 is the
|
sis0 is the external interface, on the 10.0.0.0/24 subnet; sis1 is the
|
||||||
internal interface, on the 192.168.0.0/24 subnet, and sis2 is the
|
internal interface, on the 192.168.0.0/24 subnet; and sis2 is the
|
||||||
.Nm
|
.Nm
|
||||||
interface, using the 192.168.254.0/24 subnet.
|
interface, using the 192.168.254.0/24 subnet.
|
||||||
A crossover cable connects the two firewalls via their sis2 interfaces.
|
A crossover cable connects the two firewalls via their sis2 interfaces.
|
||||||
@ -200,10 +215,12 @@ has not been ported from
|
|||||||
.Ox
|
.Ox
|
||||||
yet.
|
yet.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
|
.Xr bpf 4 ,
|
||||||
.Xr carp 4 ,
|
.Xr carp 4 ,
|
||||||
.Xr ifconfig 8 ,
|
.Xr ifconfig 8 ,
|
||||||
.Xr inet 4 ,
|
.Xr inet 4 ,
|
||||||
.Xr inet6 4 ,
|
.Xr inet6 4 ,
|
||||||
|
.Xr ipsec 4 ,
|
||||||
.Xr netintro 4 ,
|
.Xr netintro 4 ,
|
||||||
.Xr pf 4 ,
|
.Xr pf 4 ,
|
||||||
.Xr pf.conf 5 ,
|
.Xr pf.conf 5 ,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pf_print_state.c,v 1.39 2004/02/10 17:48:08 henning Exp $ */
|
/* $OpenBSD: pf_print_state.c,v 1.40 2004/12/10 22:13:26 henning Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Daniel Hartmeier
|
* Copyright (c) 2001 Daniel Hartmeier
|
||||||
@ -100,6 +100,9 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
|
|||||||
case PF_ADDR_NOROUTE:
|
case PF_ADDR_NOROUTE:
|
||||||
printf("no-route");
|
printf("no-route");
|
||||||
return;
|
return;
|
||||||
|
case PF_ADDR_RTLABEL:
|
||||||
|
printf("route \"%s\"", addr->v.rtlabelname);
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
printf("?");
|
printf("?");
|
||||||
return;
|
return;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl.h,v 1.33 2004/02/19 21:37:01 cedric Exp $ */
|
/* $OpenBSD: pfctl.h,v 1.37 2005/01/05 18:23:10 mcbride Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Daniel Hartmeier
|
* Copyright (c) 2001 Daniel Hartmeier
|
||||||
@ -65,8 +65,6 @@ int pfr_get_astats(struct pfr_table *, struct pfr_astats *, int *, int);
|
|||||||
int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||||
int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||||
int pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int);
|
int pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int);
|
||||||
int pfr_ina_begin(struct pfr_table *, int *, int *, int);
|
|
||||||
int pfr_ina_commit(struct pfr_table *, int, int *, int *, int);
|
|
||||||
int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
|
int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
|
||||||
int *, int, int);
|
int *, int, int);
|
||||||
void pfr_buf_clear(struct pfr_buffer *);
|
void pfr_buf_clear(struct pfr_buffer *);
|
||||||
@ -80,13 +78,14 @@ int pfi_get_ifaces(const char *, struct pfi_if *, int *, int);
|
|||||||
int pfi_clr_istats(const char *, int *, int);
|
int pfi_clr_istats(const char *, int *, int);
|
||||||
|
|
||||||
void pfctl_print_title(char *);
|
void pfctl_print_title(char *);
|
||||||
int pfctl_clear_tables(const char *, const char *, int);
|
int pfctl_clear_tables(const char *, int);
|
||||||
int pfctl_show_tables(const char *, const char *, int);
|
int pfctl_show_tables(const char *, int);
|
||||||
int pfctl_command_tables(int, char *[], char *, const char *, char *,
|
int pfctl_command_tables(int, char *[], char *, const char *, char *,
|
||||||
const char *, const char *, int);
|
const char *, int);
|
||||||
int pfctl_show_altq(int, const char *, int, int);
|
int pfctl_show_altq(int, const char *, int, int);
|
||||||
void warn_namespace_collision(const char *);
|
void warn_namespace_collision(const char *);
|
||||||
int pfctl_show_ifaces(const char *, int);
|
int pfctl_show_ifaces(const char *, int);
|
||||||
|
FILE *pfctl_fopen(const char *, const char *);
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
extern int altqsupport;
|
extern int altqsupport;
|
||||||
@ -108,6 +107,8 @@ struct segment {
|
|||||||
double x, y, d, m;
|
double x, y, d, m;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern int loadopt;
|
||||||
|
|
||||||
int check_commit_altq(int, int);
|
int check_commit_altq(int, int);
|
||||||
void pfaltq_store(struct pf_altq *);
|
void pfaltq_store(struct pf_altq *);
|
||||||
void pfaltq_free(struct pf_altq *);
|
void pfaltq_free(struct pf_altq *);
|
||||||
@ -121,9 +122,9 @@ void print_state(struct pf_state *, int);
|
|||||||
int unmask(struct pf_addr *, sa_family_t);
|
int unmask(struct pf_addr *, sa_family_t);
|
||||||
|
|
||||||
int pfctl_cmdline_symset(char *);
|
int pfctl_cmdline_symset(char *);
|
||||||
int pfctl_add_trans(struct pfr_buffer *, int, const char *, const char *);
|
int pfctl_add_trans(struct pfr_buffer *, int, const char *);
|
||||||
u_int32_t
|
u_int32_t
|
||||||
pfctl_get_ticket(struct pfr_buffer *, int, const char *, const char *);
|
pfctl_get_ticket(struct pfr_buffer *, int, const char *);
|
||||||
int pfctl_trans(int, struct pfr_buffer *, u_long, int);
|
int pfctl_trans(int, struct pfr_buffer *, u_long, int);
|
||||||
|
|
||||||
#endif /* _PFCTL_H_ */
|
#endif /* _PFCTL_H_ */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_altq.c,v 1.83 2004/03/14 21:51:44 dhartmei Exp $ */
|
/* $OpenBSD: pfctl_altq.c,v 1.86 2005/02/28 14:04:51 henning Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002
|
* Copyright (c) 2002
|
||||||
@ -315,7 +315,8 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
|
|||||||
struct node_queue_opt *opts)
|
struct node_queue_opt *opts)
|
||||||
{
|
{
|
||||||
/* should be merged with expand_queue */
|
/* should be merged with expand_queue */
|
||||||
struct pf_altq *if_pa, *parent;
|
struct pf_altq *if_pa, *parent, *altq;
|
||||||
|
u_int32_t bwsum;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
/* find the corresponding interface and copy fields used by queues */
|
/* find the corresponding interface and copy fields used by queues */
|
||||||
@ -347,22 +348,35 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
|
|||||||
pa->qlimit = DEFAULT_QLIMIT;
|
pa->qlimit = DEFAULT_QLIMIT;
|
||||||
|
|
||||||
if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC) {
|
if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC) {
|
||||||
if ((pa->bandwidth = eval_bwspec(bw,
|
pa->bandwidth = eval_bwspec(bw,
|
||||||
parent == NULL ? 0 : parent->bandwidth)) == 0) {
|
parent == NULL ? 0 : parent->bandwidth);
|
||||||
fprintf(stderr, "bandwidth for %s invalid (%d / %d)\n",
|
|
||||||
pa->qname, bw->bw_absolute, bw->bw_percent);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pa->bandwidth > pa->ifbandwidth) {
|
if (pa->bandwidth > pa->ifbandwidth) {
|
||||||
fprintf(stderr, "bandwidth for %s higher than "
|
fprintf(stderr, "bandwidth for %s higher than "
|
||||||
"interface\n", pa->qname);
|
"interface\n", pa->qname);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
if (parent != NULL && pa->bandwidth > parent->bandwidth) {
|
/* check the sum of the child bandwidth is under parent's */
|
||||||
fprintf(stderr, "bandwidth for %s higher than parent\n",
|
if (parent != NULL) {
|
||||||
pa->qname);
|
if (pa->bandwidth > parent->bandwidth) {
|
||||||
return (1);
|
warnx("bandwidth for %s higher than parent",
|
||||||
|
pa->qname);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
bwsum = 0;
|
||||||
|
TAILQ_FOREACH(altq, &altqs, entries) {
|
||||||
|
if (strncmp(altq->ifname, pa->ifname,
|
||||||
|
IFNAMSIZ) == 0 &&
|
||||||
|
altq->qname[0] != 0 &&
|
||||||
|
strncmp(altq->parent, pa->parent,
|
||||||
|
PF_QNAME_SIZE) == 0)
|
||||||
|
bwsum += altq->bandwidth;
|
||||||
|
}
|
||||||
|
bwsum += pa->bandwidth;
|
||||||
|
if (bwsum > parent->bandwidth) {
|
||||||
|
warnx("the sum of the child bandwidth higher"
|
||||||
|
" than parent \"%s\"", parent->qname);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,7 +720,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
* for the real-time service curve, the sum of the service curves
|
* for the real-time service curve, the sum of the service curves
|
||||||
* should not exceed 80% of the interface bandwidth. 20% is reserved
|
* should not exceed 80% of the interface bandwidth. 20% is reserved
|
||||||
* not to over-commit the actual interface bandwidth.
|
* not to over-commit the actual interface bandwidth.
|
||||||
* for the link-sharing service curve, the sum of the child service
|
* for the linkshare service curve, the sum of the child service
|
||||||
* curve should not exceed the parent service curve.
|
* curve should not exceed the parent service curve.
|
||||||
* for the upper-limit service curve, the assigned bandwidth should
|
* for the upper-limit service curve, the assigned bandwidth should
|
||||||
* be smaller than the interface bandwidth, and the upper-limit should
|
* be smaller than the interface bandwidth, and the upper-limit should
|
||||||
@ -733,7 +747,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0)
|
if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* if the class has a link-sharing service curve, add it. */
|
/* if the class has a linkshare service curve, add it. */
|
||||||
if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) {
|
if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) {
|
||||||
sc.m1 = altq->pq_u.hfsc_opts.lssc_m1;
|
sc.m1 = altq->pq_u.hfsc_opts.lssc_m1;
|
||||||
sc.d = altq->pq_u.hfsc_opts.lssc_d;
|
sc.d = altq->pq_u.hfsc_opts.lssc_d;
|
||||||
@ -744,22 +758,35 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
|
|
||||||
/* check the real-time service curve. reserve 20% of interface bw */
|
/* check the real-time service curve. reserve 20% of interface bw */
|
||||||
if (opts->rtsc_m2 != 0) {
|
if (opts->rtsc_m2 != 0) {
|
||||||
|
/* add this queue to the sum */
|
||||||
|
sc.m1 = opts->rtsc_m1;
|
||||||
|
sc.d = opts->rtsc_d;
|
||||||
|
sc.m2 = opts->rtsc_m2;
|
||||||
|
gsc_add_sc(&rtsc, &sc);
|
||||||
|
/* compare the sum with 80% of the interface */
|
||||||
sc.m1 = 0;
|
sc.m1 = 0;
|
||||||
sc.d = 0;
|
sc.d = 0;
|
||||||
sc.m2 = pa->ifbandwidth / 100 * 80;
|
sc.m2 = pa->ifbandwidth / 100 * 80;
|
||||||
if (!is_gsc_under_sc(&rtsc, &sc)) {
|
if (!is_gsc_under_sc(&rtsc, &sc)) {
|
||||||
warnx("real-time sc exceeds the interface bandwidth");
|
warnx("real-time sc exceeds 80%% of the interface "
|
||||||
|
"bandwidth (%s)", rate2str((double)sc.m2));
|
||||||
goto err_ret;
|
goto err_ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check the link-sharing service curve. */
|
/* check the linkshare service curve. */
|
||||||
if (opts->lssc_m2 != 0) {
|
if (opts->lssc_m2 != 0) {
|
||||||
|
/* add this queue to the child sum */
|
||||||
|
sc.m1 = opts->lssc_m1;
|
||||||
|
sc.d = opts->lssc_d;
|
||||||
|
sc.m2 = opts->lssc_m2;
|
||||||
|
gsc_add_sc(&lssc, &sc);
|
||||||
|
/* compare the sum of the children with parent's sc */
|
||||||
sc.m1 = parent->pq_u.hfsc_opts.lssc_m1;
|
sc.m1 = parent->pq_u.hfsc_opts.lssc_m1;
|
||||||
sc.d = parent->pq_u.hfsc_opts.lssc_d;
|
sc.d = parent->pq_u.hfsc_opts.lssc_d;
|
||||||
sc.m2 = parent->pq_u.hfsc_opts.lssc_m2;
|
sc.m2 = parent->pq_u.hfsc_opts.lssc_m2;
|
||||||
if (!is_gsc_under_sc(&lssc, &sc)) {
|
if (!is_gsc_under_sc(&lssc, &sc)) {
|
||||||
warnx("link-sharing sc exceeds parent's sc");
|
warnx("linkshare sc exceeds parent's sc");
|
||||||
goto err_ret;
|
goto err_ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1108,6 +1135,7 @@ getifspeed(char *ifname)
|
|||||||
|
|
||||||
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||||
err(1, "socket");
|
err(1, "socket");
|
||||||
|
bzero(&ifr, sizeof(ifr));
|
||||||
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
|
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
|
||||||
sizeof(ifr.ifr_name))
|
sizeof(ifr.ifr_name))
|
||||||
errx(1, "getifspeed: strlcpy");
|
errx(1, "getifspeed: strlcpy");
|
||||||
@ -1130,6 +1158,7 @@ getifmtu(char *ifname)
|
|||||||
|
|
||||||
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||||
err(1, "socket");
|
err(1, "socket");
|
||||||
|
bzero(&ifr, sizeof(ifr));
|
||||||
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
|
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
|
||||||
sizeof(ifr.ifr_name))
|
sizeof(ifr.ifr_name))
|
||||||
errx(1, "getifmtu: strlcpy");
|
errx(1, "getifmtu: strlcpy");
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@ -815,7 +818,11 @@ block_feedback(struct pfctl *pf, struct superblock *block)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
if (por2 == NULL)
|
||||||
|
#else
|
||||||
if (por2 == TAILQ_END(&block->sb_rules))
|
if (por2 == TAILQ_END(&block->sb_rules))
|
||||||
|
#endif
|
||||||
TAILQ_INSERT_TAIL(&block->sb_rules, por1, por_entry);
|
TAILQ_INSERT_TAIL(&block->sb_rules, por1, por_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_parser.c,v 1.194 2004/03/15 15:25:44 dhartmei Exp $ */
|
/* $OpenBSD: pfctl_parser.c,v 1.211 2004/12/07 10:33:41 dhartmei Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Daniel Hartmeier
|
* Copyright (c) 2001 Daniel Hartmeier
|
||||||
@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/proc.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
@ -66,6 +68,7 @@ void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned);
|
|||||||
void print_flags (u_int8_t);
|
void print_flags (u_int8_t);
|
||||||
void print_fromto(struct pf_rule_addr *, pf_osfp_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 ifa_skip_if(const char *filter, struct node_host *p);
|
||||||
|
|
||||||
struct node_host *host_if(const char *, int);
|
struct node_host *host_if(const char *, int);
|
||||||
struct node_host *host_v4(const char *, int);
|
struct node_host *host_v4(const char *, int);
|
||||||
@ -186,6 +189,7 @@ const struct pf_timeout pf_timeouts[] = {
|
|||||||
{ "tcp.closing", PFTM_TCP_CLOSING },
|
{ "tcp.closing", PFTM_TCP_CLOSING },
|
||||||
{ "tcp.finwait", PFTM_TCP_FIN_WAIT },
|
{ "tcp.finwait", PFTM_TCP_FIN_WAIT },
|
||||||
{ "tcp.closed", PFTM_TCP_CLOSED },
|
{ "tcp.closed", PFTM_TCP_CLOSED },
|
||||||
|
{ "tcp.tsdiff", PFTM_TS_DIFF },
|
||||||
{ "udp.first", PFTM_UDP_FIRST_PACKET },
|
{ "udp.first", PFTM_UDP_FIRST_PACKET },
|
||||||
{ "udp.single", PFTM_UDP_SINGLE },
|
{ "udp.single", PFTM_UDP_SINGLE },
|
||||||
{ "udp.multiple", PFTM_UDP_MULTIPLE },
|
{ "udp.multiple", PFTM_UDP_MULTIPLE },
|
||||||
@ -366,13 +370,13 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst,
|
|||||||
PF_AZERO(&src->addr.v.a.mask, AF_INET6) &&
|
PF_AZERO(&src->addr.v.a.mask, AF_INET6) &&
|
||||||
PF_AZERO(&dst->addr.v.a.addr, AF_INET6) &&
|
PF_AZERO(&dst->addr.v.a.addr, AF_INET6) &&
|
||||||
PF_AZERO(&dst->addr.v.a.mask, AF_INET6) &&
|
PF_AZERO(&dst->addr.v.a.mask, AF_INET6) &&
|
||||||
!src->not && !dst->not &&
|
!src->neg && !dst->neg &&
|
||||||
!src->port_op && !dst->port_op &&
|
!src->port_op && !dst->port_op &&
|
||||||
osfp == PF_OSFP_ANY)
|
osfp == PF_OSFP_ANY)
|
||||||
printf(" all");
|
printf(" all");
|
||||||
else {
|
else {
|
||||||
printf(" from ");
|
printf(" from ");
|
||||||
if (src->not)
|
if (src->neg)
|
||||||
printf("! ");
|
printf("! ");
|
||||||
print_addr(&src->addr, af, verbose);
|
print_addr(&src->addr, af, verbose);
|
||||||
if (src->port_op)
|
if (src->port_op)
|
||||||
@ -384,7 +388,7 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst,
|
|||||||
sizeof(buf)));
|
sizeof(buf)));
|
||||||
|
|
||||||
printf(" to ");
|
printf(" to ");
|
||||||
if (dst->not)
|
if (dst->neg)
|
||||||
printf("! ");
|
printf("! ");
|
||||||
print_addr(&dst->addr, af, verbose);
|
print_addr(&dst->addr, af, verbose);
|
||||||
if (dst->port_op)
|
if (dst->port_op)
|
||||||
@ -472,6 +476,7 @@ print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
|
const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
|
||||||
|
const char *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES;
|
||||||
const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
|
const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
|
||||||
const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
|
const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
|
||||||
|
|
||||||
@ -574,6 +579,22 @@ print_status(struct pf_status *s, int opts)
|
|||||||
else
|
else
|
||||||
printf("%14s\n", "");
|
printf("%14s\n", "");
|
||||||
}
|
}
|
||||||
|
if (opts & PF_OPT_VERBOSE) {
|
||||||
|
printf("Limit Counters\n");
|
||||||
|
for (i = 0; i < LCNT_MAX; i++) {
|
||||||
|
printf(" %-25s %14lld ", pf_lcounters[i],
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
(unsigned long long)s->lcounters[i]);
|
||||||
|
#else
|
||||||
|
s->lcounters[i]);
|
||||||
|
#endif
|
||||||
|
if (runtime > 0)
|
||||||
|
printf("%14.1f/s\n",
|
||||||
|
(double)s->lcounters[i] / (double)runtime);
|
||||||
|
else
|
||||||
|
printf("%14s\n", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -593,7 +614,9 @@ print_src_node(struct pf_src_node *sn, int opts)
|
|||||||
printf(" -> ");
|
printf(" -> ");
|
||||||
aw.v.a.addr = sn->raddr;
|
aw.v.a.addr = sn->raddr;
|
||||||
print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
|
print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
|
||||||
printf(" (%d states)\n", sn->states);
|
printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states,
|
||||||
|
sn->conn, sn->conn_rate.count / 1000,
|
||||||
|
(sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds);
|
||||||
if (opts & PF_OPT_VERBOSE) {
|
if (opts & PF_OPT_VERBOSE) {
|
||||||
sec = sn->creation % 60;
|
sec = sn->creation % 60;
|
||||||
sn->creation /= 60;
|
sn->creation /= 60;
|
||||||
@ -628,21 +651,22 @@ print_src_node(struct pf_src_node *sn, int opts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_rule(struct pf_rule *r, int verbose)
|
print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
||||||
{
|
{
|
||||||
static const char *actiontypes[] = { "pass", "block", "scrub", "nat",
|
static const char *actiontypes[] = { "pass", "block", "scrub",
|
||||||
"no nat", "binat", "no binat", "rdr", "no rdr" };
|
"no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" };
|
||||||
static const char *anchortypes[] = { "anchor", "anchor", "anchor",
|
static const char *anchortypes[] = { "anchor", "anchor", "anchor",
|
||||||
"nat-anchor", "nat-anchor", "binat-anchor", "binat-anchor",
|
"anchor", "nat-anchor", "nat-anchor", "binat-anchor",
|
||||||
"rdr-anchor", "rdr-anchor" };
|
"binat-anchor", "rdr-anchor", "rdr-anchor" };
|
||||||
int i, opts;
|
int i, opts;
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("@%d ", r->nr);
|
printf("@%d ", r->nr);
|
||||||
if (r->action > PF_NORDR)
|
if (r->action > PF_NORDR)
|
||||||
printf("action(%d)", r->action);
|
printf("action(%d)", r->action);
|
||||||
else if (r->anchorname[0])
|
else if (anchor_call[0])
|
||||||
printf("%s %s", anchortypes[r->action], r->anchorname);
|
printf("%s \"%s\"", anchortypes[r->action],
|
||||||
|
anchor_call);
|
||||||
else {
|
else {
|
||||||
printf("%s", actiontypes[r->action]);
|
printf("%s", actiontypes[r->action]);
|
||||||
if (r->natpass)
|
if (r->natpass)
|
||||||
@ -782,6 +806,21 @@ print_rule(struct pf_rule *r, int verbose)
|
|||||||
printf(" modulate state");
|
printf(" modulate state");
|
||||||
else if (r->keep_state == PF_STATE_SYNPROXY)
|
else if (r->keep_state == PF_STATE_SYNPROXY)
|
||||||
printf(" synproxy state");
|
printf(" synproxy state");
|
||||||
|
if (r->prob) {
|
||||||
|
char buf[20];
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0));
|
||||||
|
for (i = strlen(buf)-1; i > 0; i--) {
|
||||||
|
if (buf[i] == '0')
|
||||||
|
buf[i] = '\0';
|
||||||
|
else {
|
||||||
|
if (buf[i] == '.')
|
||||||
|
buf[i] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(" probability %s%%", buf);
|
||||||
|
}
|
||||||
opts = 0;
|
opts = 0;
|
||||||
if (r->max_states || r->max_src_nodes || r->max_src_states)
|
if (r->max_states || r->max_src_nodes || r->max_src_states)
|
||||||
opts = 1;
|
opts = 1;
|
||||||
@ -822,12 +861,35 @@ print_rule(struct pf_rule *r, int verbose)
|
|||||||
printf("max-src-states %u", r->max_src_states);
|
printf("max-src-states %u", r->max_src_states);
|
||||||
opts = 0;
|
opts = 0;
|
||||||
}
|
}
|
||||||
|
if (r->max_src_conn) {
|
||||||
|
if (!opts)
|
||||||
|
printf(", ");
|
||||||
|
printf("max-src-conn %u", r->max_src_conn);
|
||||||
|
opts = 0;
|
||||||
|
}
|
||||||
|
if (r->max_src_conn_rate.limit) {
|
||||||
|
if (!opts)
|
||||||
|
printf(", ");
|
||||||
|
printf("max-src-conn-rate %u/%u",
|
||||||
|
r->max_src_conn_rate.limit,
|
||||||
|
r->max_src_conn_rate.seconds);
|
||||||
|
opts = 0;
|
||||||
|
}
|
||||||
if (r->max_src_nodes) {
|
if (r->max_src_nodes) {
|
||||||
if (!opts)
|
if (!opts)
|
||||||
printf(", ");
|
printf(", ");
|
||||||
printf("max-src-nodes %u", r->max_src_nodes);
|
printf("max-src-nodes %u", r->max_src_nodes);
|
||||||
opts = 0;
|
opts = 0;
|
||||||
}
|
}
|
||||||
|
if (r->overload_tblname[0]) {
|
||||||
|
if (!opts)
|
||||||
|
printf(", ");
|
||||||
|
printf("overload <%s>", r->overload_tblname);
|
||||||
|
if (r->flush)
|
||||||
|
printf(" flush");
|
||||||
|
if (r->flush & PF_FLUSH_GLOBAL)
|
||||||
|
printf(" global");
|
||||||
|
}
|
||||||
if (r->rule_flag & PFRULE_IFBOUND) {
|
if (r->rule_flag & PFRULE_IFBOUND) {
|
||||||
if (!opts)
|
if (!opts)
|
||||||
printf(", ");
|
printf(", ");
|
||||||
@ -842,11 +904,17 @@ print_rule(struct pf_rule *r, int verbose)
|
|||||||
}
|
}
|
||||||
for (i = 0; i < PFTM_MAX; ++i)
|
for (i = 0; i < PFTM_MAX; ++i)
|
||||||
if (r->timeout[i]) {
|
if (r->timeout[i]) {
|
||||||
|
int j;
|
||||||
|
|
||||||
if (!opts)
|
if (!opts)
|
||||||
printf(", ");
|
printf(", ");
|
||||||
opts = 0;
|
opts = 0;
|
||||||
printf("%s %u", pf_timeouts[i].name,
|
for (j = 0; j < sizeof(pf_timeouts) /
|
||||||
r->timeout[i]);
|
sizeof(pf_timeouts[0]); ++j)
|
||||||
|
if (pf_timeouts[j].timeout == i)
|
||||||
|
break;
|
||||||
|
printf("%s %u", j == PFTM_MAX ? "inv.timeout" :
|
||||||
|
pf_timeouts[j].name, r->timeout[i]);
|
||||||
}
|
}
|
||||||
printf(")");
|
printf(")");
|
||||||
}
|
}
|
||||||
@ -886,7 +954,7 @@ print_rule(struct pf_rule *r, int verbose)
|
|||||||
printf(" !");
|
printf(" !");
|
||||||
printf(" tagged %s", r->match_tagname);
|
printf(" tagged %s", r->match_tagname);
|
||||||
}
|
}
|
||||||
if (!r->anchorname[0] && (r->action == PF_NAT ||
|
if (!anchor_call[0] && (r->action == PF_NAT ||
|
||||||
r->action == PF_BINAT || r->action == PF_RDR)) {
|
r->action == PF_BINAT || r->action == PF_RDR)) {
|
||||||
printf(" -> ");
|
printf(" -> ");
|
||||||
print_pool(&r->rpool, r->rpool.proxy_port[0],
|
print_pool(&r->rpool, r->rpool.proxy_port[0],
|
||||||
@ -953,9 +1021,7 @@ set_ipmask(struct node_host *h, u_int8_t b)
|
|||||||
int i, j = 0;
|
int i, j = 0;
|
||||||
|
|
||||||
m = &h->addr.v.a.mask;
|
m = &h->addr.v.a.mask;
|
||||||
|
memset(m, 0, sizeof(*m));
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
m->addr32[i] = 0;
|
|
||||||
|
|
||||||
while (b >= 32) {
|
while (b >= 32) {
|
||||||
m->addr32[j++] = 0xffffffff;
|
m->addr32[j++] = 0xffffffff;
|
||||||
@ -1007,8 +1073,6 @@ ifa_load(void)
|
|||||||
{
|
{
|
||||||
struct ifaddrs *ifap, *ifa;
|
struct ifaddrs *ifap, *ifa;
|
||||||
struct node_host *n = NULL, *h = NULL;
|
struct node_host *n = NULL, *h = NULL;
|
||||||
struct pfr_buffer b;
|
|
||||||
struct pfi_if *p;
|
|
||||||
|
|
||||||
if (getifaddrs(&ifap) < 0)
|
if (getifaddrs(&ifap) < 0)
|
||||||
err(1, "getifaddrs");
|
err(1, "getifaddrs");
|
||||||
@ -1084,43 +1148,6 @@ ifa_load(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add interface groups, including clonable and dynamic stuff */
|
|
||||||
bzero(&b, sizeof(b));
|
|
||||||
b.pfrb_type = PFRB_IFACES;
|
|
||||||
for (;;) {
|
|
||||||
if (pfr_buf_grow(&b, b.pfrb_size))
|
|
||||||
err(1, "ifa_load: pfr_buf_grow");
|
|
||||||
b.pfrb_size = b.pfrb_msize;
|
|
||||||
if (pfi_get_ifaces(NULL, b.pfrb_caddr, &b.pfrb_size,
|
|
||||||
PFI_FLAG_GROUP))
|
|
||||||
err(1, "ifa_load: pfi_get_ifaces");
|
|
||||||
if (b.pfrb_size <= b.pfrb_msize)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
PFRB_FOREACH(p, &b) {
|
|
||||||
n = calloc(1, sizeof(struct node_host));
|
|
||||||
if (n == NULL)
|
|
||||||
err(1, "address: calloc");
|
|
||||||
n->af = AF_LINK;
|
|
||||||
n->ifa_flags = PF_IFA_FLAG_GROUP;
|
|
||||||
if (p->pfif_flags & PFI_IFLAG_DYNAMIC)
|
|
||||||
n->ifa_flags |= PF_IFA_FLAG_DYNAMIC;
|
|
||||||
if (p->pfif_flags & PFI_IFLAG_CLONABLE)
|
|
||||||
n->ifa_flags |= PF_IFA_FLAG_CLONABLE;
|
|
||||||
if (!strcmp(p->pfif_name, "lo"))
|
|
||||||
n->ifa_flags |= IFF_LOOPBACK;
|
|
||||||
if ((n->ifname = strdup(p->pfif_name)) == NULL)
|
|
||||||
err(1, "ifa_load: strdup");
|
|
||||||
n->next = NULL;
|
|
||||||
n->tail = n;
|
|
||||||
if (h == NULL)
|
|
||||||
h = n;
|
|
||||||
else {
|
|
||||||
h->tail->next = n;
|
|
||||||
h->tail = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iftab = h;
|
iftab = h;
|
||||||
freeifaddrs(ifap);
|
freeifaddrs(ifap);
|
||||||
}
|
}
|
||||||
@ -1129,12 +1156,7 @@ struct node_host *
|
|||||||
ifa_exists(const char *ifa_name, int group_ok)
|
ifa_exists(const char *ifa_name, int group_ok)
|
||||||
{
|
{
|
||||||
struct node_host *n;
|
struct node_host *n;
|
||||||
char *p, buf[IFNAMSIZ];
|
|
||||||
int group;
|
|
||||||
|
|
||||||
group = !isdigit(ifa_name[strlen(ifa_name) - 1]);
|
|
||||||
if (group && !group_ok)
|
|
||||||
return (NULL);
|
|
||||||
if (iftab == NULL)
|
if (iftab == NULL)
|
||||||
ifa_load();
|
ifa_load();
|
||||||
|
|
||||||
@ -1142,19 +1164,7 @@ ifa_exists(const char *ifa_name, int group_ok)
|
|||||||
if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
|
if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
|
||||||
return (n);
|
return (n);
|
||||||
}
|
}
|
||||||
if (!group) {
|
|
||||||
/* look for clonable and/or dynamic interface */
|
|
||||||
strlcpy(buf, ifa_name, sizeof(buf));
|
|
||||||
for (p = buf + strlen(buf) - 1; p > buf && isdigit(*p); p--)
|
|
||||||
*p = '\0';
|
|
||||||
for (n = iftab; n != NULL; n = n->next)
|
|
||||||
if (n->af == AF_LINK &&
|
|
||||||
!strncmp(n->ifname, buf, IFNAMSIZ))
|
|
||||||
break;
|
|
||||||
if (n != NULL && n->ifa_flags &
|
|
||||||
(PF_IFA_FLAG_DYNAMIC | PF_IFA_FLAG_CLONABLE))
|
|
||||||
return (n); /* XXX */
|
|
||||||
}
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1162,19 +1172,17 @@ struct node_host *
|
|||||||
ifa_lookup(const char *ifa_name, int flags)
|
ifa_lookup(const char *ifa_name, int flags)
|
||||||
{
|
{
|
||||||
struct node_host *p = NULL, *h = NULL, *n = NULL;
|
struct node_host *p = NULL, *h = NULL, *n = NULL;
|
||||||
int return_all = 0, got4 = 0, got6 = 0;
|
int got4 = 0, got6 = 0;
|
||||||
const char *last_if = NULL;
|
const char *last_if = NULL;
|
||||||
|
|
||||||
if (!strncmp(ifa_name, "self", IFNAMSIZ))
|
if (!strncmp(ifa_name, "self", IFNAMSIZ))
|
||||||
return_all = 1;
|
ifa_name = NULL;
|
||||||
|
|
||||||
if (iftab == NULL)
|
if (iftab == NULL)
|
||||||
ifa_load();
|
ifa_load();
|
||||||
|
|
||||||
for (p = iftab; p; p = p->next) {
|
for (p = iftab; p; p = p->next) {
|
||||||
if (!((p->af == AF_INET || p->af == AF_INET6) &&
|
if (ifa_skip_if(ifa_name, p))
|
||||||
(!strncmp(p->ifname, ifa_name, strlen(ifa_name)) ||
|
|
||||||
return_all)))
|
|
||||||
continue;
|
continue;
|
||||||
if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET)
|
if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET)
|
||||||
continue;
|
continue;
|
||||||
@ -1238,6 +1246,28 @@ ifa_lookup(const char *ifa_name, int flags)
|
|||||||
return (h);
|
return (h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ifa_skip_if(const char *filter, struct node_host *p)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (p->af != AF_INET && p->af != AF_INET6)
|
||||||
|
return (1);
|
||||||
|
if (filter == NULL || !*filter)
|
||||||
|
return (0);
|
||||||
|
if (!strcmp(p->ifname, filter))
|
||||||
|
return (0); /* exact match */
|
||||||
|
n = strlen(filter);
|
||||||
|
if (n < 1 || n >= IFNAMSIZ)
|
||||||
|
return (1); /* sanity check */
|
||||||
|
if (filter[n-1] >= '0' && filter[n-1] <= '9')
|
||||||
|
return (1); /* only do exact match in that case */
|
||||||
|
if (strncmp(p->ifname, filter, n))
|
||||||
|
return (1); /* prefix doesn't match */
|
||||||
|
return (p->ifname[n] < '0' || p->ifname[n] > '9');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct node_host *
|
struct node_host *
|
||||||
host(const char *s)
|
host(const char *s)
|
||||||
{
|
{
|
||||||
@ -1248,7 +1278,7 @@ host(const char *s)
|
|||||||
if ((p = strrchr(s, '/')) != NULL) {
|
if ((p = strrchr(s, '/')) != NULL) {
|
||||||
mask = strtol(p+1, &q, 0);
|
mask = strtol(p+1, &q, 0);
|
||||||
if (!q || *q || mask > 128 || q == (p+1)) {
|
if (!q || *q || mask > 128 || q == (p+1)) {
|
||||||
fprintf(stderr, "invalid netmask\n");
|
fprintf(stderr, "invalid netmask '%s'\n", p);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
|
if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
|
||||||
@ -1402,7 +1432,7 @@ host_dns(const char *s, int v4mask, int v6mask)
|
|||||||
char *p, *ps;
|
char *p, *ps;
|
||||||
|
|
||||||
if ((ps = strdup(s)) == NULL)
|
if ((ps = strdup(s)) == NULL)
|
||||||
err(1, "host_if: strdup");
|
err(1, "host_dns: strdup");
|
||||||
if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) {
|
if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) {
|
||||||
noalias = 1;
|
noalias = 1;
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
@ -1411,8 +1441,10 @@ host_dns(const char *s, int v4mask, int v6mask)
|
|||||||
hints.ai_family = PF_UNSPEC;
|
hints.ai_family = PF_UNSPEC;
|
||||||
hints.ai_socktype = SOCK_STREAM; /* DUMMY */
|
hints.ai_socktype = SOCK_STREAM; /* DUMMY */
|
||||||
error = getaddrinfo(ps, NULL, &hints, &res0);
|
error = getaddrinfo(ps, NULL, &hints, &res0);
|
||||||
if (error)
|
if (error) {
|
||||||
|
free(ps);
|
||||||
return (h);
|
return (h);
|
||||||
|
}
|
||||||
|
|
||||||
for (res = res0; res; res = res->ai_next) {
|
for (res = res0; res; res = res->ai_next) {
|
||||||
if (res->ai_family != AF_INET &&
|
if (res->ai_family != AF_INET &&
|
||||||
@ -1536,33 +1568,28 @@ append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor,
|
pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor)
|
||||||
const char *ruleset)
|
|
||||||
{
|
{
|
||||||
struct pfioc_trans_e trans;
|
struct pfioc_trans_e trans;
|
||||||
|
|
||||||
bzero(&trans, sizeof(trans));
|
bzero(&trans, sizeof(trans));
|
||||||
trans.rs_num = rs_num;
|
trans.rs_num = rs_num;
|
||||||
if (strlcpy(trans.anchor, anchor,
|
if (strlcpy(trans.anchor, anchor,
|
||||||
sizeof(trans.anchor)) >= sizeof(trans.anchor) ||
|
sizeof(trans.anchor)) >= sizeof(trans.anchor))
|
||||||
strlcpy(trans.ruleset, ruleset,
|
|
||||||
sizeof(trans.ruleset)) >= sizeof(trans.ruleset))
|
|
||||||
errx(1, "pfctl_add_trans: strlcpy");
|
errx(1, "pfctl_add_trans: strlcpy");
|
||||||
|
|
||||||
return pfr_buf_add(buf, &trans);
|
return pfr_buf_add(buf, &trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int32_t
|
u_int32_t
|
||||||
pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor,
|
pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor)
|
||||||
const char *ruleset)
|
|
||||||
{
|
{
|
||||||
struct pfioc_trans_e *p;
|
struct pfioc_trans_e *p;
|
||||||
|
|
||||||
PFRB_FOREACH(p, buf)
|
PFRB_FOREACH(p, buf)
|
||||||
if (rs_num == p->rs_num && !strcmp(anchor, p->anchor) &&
|
if (rs_num == p->rs_num && !strcmp(anchor, p->anchor))
|
||||||
!strcmp(ruleset, p->ruleset))
|
|
||||||
return (p->ticket);
|
return (p->ticket);
|
||||||
errx(1, "pfr_get_ticket: assertion failed");
|
errx(1, "pfctl_get_ticket: assertion failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_parser.h,v 1.74 2004/02/10 22:26:56 dhartmei Exp $ */
|
/* $OpenBSD: pfctl_parser.h,v 1.80 2005/02/07 18:18:14 david Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Daniel Hartmeier
|
* Copyright (c) 2001 Daniel Hartmeier
|
||||||
@ -47,6 +47,9 @@
|
|||||||
#define PF_OPT_DUMMYACTION 0x0100
|
#define PF_OPT_DUMMYACTION 0x0100
|
||||||
#define PF_OPT_DEBUG 0x0200
|
#define PF_OPT_DEBUG 0x0200
|
||||||
#define PF_OPT_SHOWALL 0x0400
|
#define PF_OPT_SHOWALL 0x0400
|
||||||
|
#define PF_OPT_OPTIMIZE 0x0800
|
||||||
|
#define PF_OPT_OPTIMIZE_PROFILE 0x1000
|
||||||
|
#define PF_OPT_MERGE 0x2000
|
||||||
|
|
||||||
#define PF_TH_ALL 0xFF
|
#define PF_TH_ALL 0xFF
|
||||||
|
|
||||||
@ -60,6 +63,11 @@
|
|||||||
NULL \
|
NULL \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct pfr_buffer; /* forward definition */
|
||||||
|
struct pf_opt_rule;
|
||||||
|
TAILQ_HEAD(pf_opt_queue, pf_opt_rule);
|
||||||
|
|
||||||
|
|
||||||
struct pfctl {
|
struct pfctl {
|
||||||
int dev;
|
int dev;
|
||||||
int opts;
|
int opts;
|
||||||
@ -73,11 +81,26 @@ struct pfctl {
|
|||||||
struct pfr_buffer *trans;
|
struct pfr_buffer *trans;
|
||||||
const char *anchor;
|
const char *anchor;
|
||||||
const char *ruleset;
|
const char *ruleset;
|
||||||
|
struct pf_opt_queue opt_queue;
|
||||||
|
|
||||||
|
/* 'set foo' options */
|
||||||
|
u_int32_t timeout[PFTM_MAX];
|
||||||
|
u_int32_t limit[PF_LIMIT_MAX];
|
||||||
|
u_int32_t debug;
|
||||||
|
u_int32_t hostid;
|
||||||
|
char *ifname;
|
||||||
|
|
||||||
|
u_int8_t timeout_set[PFTM_MAX];
|
||||||
|
u_int8_t limit_set[PF_LIMIT_MAX];
|
||||||
|
u_int8_t debug_set;
|
||||||
|
u_int8_t hostid_set;
|
||||||
|
u_int8_t ifname_set;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node_if {
|
struct node_if {
|
||||||
char ifname[IFNAMSIZ];
|
char ifname[IFNAMSIZ];
|
||||||
u_int8_t not;
|
u_int8_t not;
|
||||||
|
u_int8_t dynamic; /* antispoof */
|
||||||
u_int ifa_flags;
|
u_int ifa_flags;
|
||||||
struct node_if *next;
|
struct node_if *next;
|
||||||
struct node_if *tail;
|
struct node_if *tail;
|
||||||
@ -166,11 +189,33 @@ struct node_tinit { /* table initializer */
|
|||||||
char *file;
|
char *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pfr_buffer; /* forward definition */
|
|
||||||
|
|
||||||
int pfctl_rules(int, char *, int, char *, char *, struct pfr_buffer *);
|
/* optimizer created tables */
|
||||||
|
struct pf_opt_tbl {
|
||||||
|
char pt_name[PF_TABLE_NAME_SIZE];
|
||||||
|
int pt_rulecount;
|
||||||
|
int pt_generated;
|
||||||
|
struct node_tinithead pt_nodes;
|
||||||
|
struct pfr_buffer *pt_buf;
|
||||||
|
};
|
||||||
|
#define PF_OPT_TABLE_PREFIX "__automatic_"
|
||||||
|
|
||||||
int pfctl_add_rule(struct pfctl *, struct pf_rule *);
|
/* optimizer pf_rule container */
|
||||||
|
struct pf_opt_rule {
|
||||||
|
struct pf_rule por_rule;
|
||||||
|
struct pf_opt_tbl *por_src_tbl;
|
||||||
|
struct pf_opt_tbl *por_dst_tbl;
|
||||||
|
char por_anchor[MAXPATHLEN];
|
||||||
|
u_int64_t por_profile_count;
|
||||||
|
TAILQ_ENTRY(pf_opt_rule) por_entry;
|
||||||
|
TAILQ_ENTRY(pf_opt_rule) por_skip_entry[PF_SKIP_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int pfctl_rules(int, char *, int, char *, struct pfr_buffer *);
|
||||||
|
int pfctl_optimize_rules(struct pfctl *);
|
||||||
|
|
||||||
|
int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *);
|
||||||
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
|
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
|
||||||
int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t);
|
int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t);
|
||||||
void pfctl_clear_pool(struct pf_pool *);
|
void pfctl_clear_pool(struct pf_pool *);
|
||||||
@ -181,6 +226,7 @@ int pfctl_set_limit(struct pfctl *, const char *, unsigned int);
|
|||||||
int pfctl_set_logif(struct pfctl *, char *);
|
int pfctl_set_logif(struct pfctl *, char *);
|
||||||
int pfctl_set_hostid(struct pfctl *, u_int32_t);
|
int pfctl_set_hostid(struct pfctl *, u_int32_t);
|
||||||
int pfctl_set_debug(struct pfctl *, char *);
|
int pfctl_set_debug(struct pfctl *, char *);
|
||||||
|
int pfctl_set_interface_flags(struct pfctl *, char *, int, int);
|
||||||
|
|
||||||
int parse_rules(FILE *, struct pfctl *);
|
int parse_rules(FILE *, struct pfctl *);
|
||||||
int parse_flags(char *);
|
int parse_flags(char *);
|
||||||
@ -188,7 +234,7 @@ int pfctl_load_anchors(int, int, struct pfr_buffer *);
|
|||||||
|
|
||||||
void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int);
|
void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int);
|
||||||
void print_src_node(struct pf_src_node *, int);
|
void print_src_node(struct pf_src_node *, int);
|
||||||
void print_rule(struct pf_rule *, int);
|
void print_rule(struct pf_rule *, const char *, int);
|
||||||
void print_tabledef(const char *, int, int, struct node_tinithead *);
|
void print_tabledef(const char *, int, int, struct node_tinithead *);
|
||||||
void print_status(struct pf_status *, int);
|
void print_status(struct pf_status *, int);
|
||||||
|
|
||||||
@ -202,8 +248,8 @@ void print_altq(const struct pf_altq *, unsigned, struct node_queue_bw *,
|
|||||||
void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *,
|
void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *,
|
||||||
int, struct node_queue_opt *);
|
int, struct node_queue_opt *);
|
||||||
|
|
||||||
int pfctl_define_table(char *, int, int, const char *, const char *,
|
int pfctl_define_table(char *, int, int, const char *, struct pfr_buffer *,
|
||||||
struct pfr_buffer *, u_int32_t);
|
u_int32_t);
|
||||||
|
|
||||||
void pfctl_clear_fingerprints(int, int);
|
void pfctl_clear_fingerprints(int, int);
|
||||||
int pfctl_file_fingerprints(int, int, const char *);
|
int pfctl_file_fingerprints(int, int, const char *);
|
||||||
@ -244,6 +290,7 @@ extern const struct pf_timeout pf_timeouts[];
|
|||||||
|
|
||||||
void set_ipmask(struct node_host *, u_int8_t);
|
void set_ipmask(struct node_host *, u_int8_t);
|
||||||
int check_netmask(struct node_host *, sa_family_t);
|
int check_netmask(struct node_host *, sa_family_t);
|
||||||
|
int unmask(struct pf_addr *, sa_family_t);
|
||||||
void ifa_load(void);
|
void ifa_load(void);
|
||||||
struct node_host *ifa_exists(const char *, int);
|
struct node_host *ifa_exists(const char *, int);
|
||||||
struct node_host *ifa_lookup(const char *, int);
|
struct node_host *ifa_lookup(const char *, int);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_qstats.c,v 1.29 2004/03/15 15:25:44 dhartmei Exp $ */
|
/* $OpenBSD: pfctl_qstats.c,v 1.30 2004/04/27 21:47:32 kjc Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Henning Brauer <henning@openbsd.org>
|
* Copyright (c) Henning Brauer <henning@openbsd.org>
|
||||||
@ -97,6 +97,8 @@ pfctl_show_altq(int dev, const char *iface, int opts, int verbose2)
|
|||||||
if ((nodes = pfctl_update_qstats(dev, &root)) < 0)
|
if ((nodes = pfctl_update_qstats(dev, &root)) < 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
|
if (nodes == 0)
|
||||||
|
printf("No queue in use\n");
|
||||||
for (node = root; node != NULL; node = node->next) {
|
for (node = root; node != NULL; node = node->next) {
|
||||||
if (iface != NULL && strcmp(node->altq.ifname, iface))
|
if (iface != NULL && strcmp(node->altq.ifname, iface))
|
||||||
continue;
|
continue;
|
||||||
@ -107,11 +109,11 @@ pfctl_show_altq(int dev, const char *iface, int opts, int verbose2)
|
|||||||
pfctl_print_altq_node(dev, node, 0, opts);
|
pfctl_print_altq_node(dev, node, 0, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (verbose2) {
|
while (verbose2 && nodes > 0) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
sleep(STAT_INTERVAL);
|
sleep(STAT_INTERVAL);
|
||||||
if (pfctl_update_qstats(dev, &root) == -1)
|
if ((nodes = pfctl_update_qstats(dev, &root)) == -1)
|
||||||
return (-1);
|
return (-1);
|
||||||
for (node = root; node != NULL; node = node->next) {
|
for (node = root; node != NULL; node = node->next) {
|
||||||
if (iface != NULL && strcmp(node->altq.ifname, iface))
|
if (iface != NULL && strcmp(node->altq.ifname, iface))
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_table.c,v 1.59 2004/03/15 15:25:44 dhartmei Exp $ */
|
/* $OpenBSD: pfctl_table.c,v 1.62 2004/12/22 17:17:55 dhartmei Exp $ */
|
||||||
/* add $OpenBSD: pfctl_table.c,v 1.61 2004/06/12 22:22:44 cedric Exp $ */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002 Cedric Berger
|
* Copyright (c) 2002 Cedric Berger
|
||||||
@ -57,7 +56,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
extern void usage(void);
|
extern void usage(void);
|
||||||
static int pfctl_table(int, char *[], char *, const char *, char *,
|
static int pfctl_table(int, char *[], char *, const char *, char *,
|
||||||
const char *, const char *, int);
|
const char *, int);
|
||||||
static void print_table(struct pfr_table *, int, int);
|
static void print_table(struct pfr_table *, int, int);
|
||||||
static void print_tstats(struct pfr_tstats *, int);
|
static void print_tstats(struct pfr_tstats *, int);
|
||||||
static int load_addr(struct pfr_buffer *, int, char *[], char *, int);
|
static int load_addr(struct pfr_buffer *, int, char *[], char *, int);
|
||||||
@ -106,31 +105,29 @@ static const char *istats_text[2][2][2] = {
|
|||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
int
|
int
|
||||||
pfctl_clear_tables(const char *anchor, const char *ruleset, int opts)
|
pfctl_clear_tables(const char *anchor, int opts)
|
||||||
{
|
{
|
||||||
return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, ruleset, opts);
|
return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pfctl_show_tables(const char *anchor, const char *ruleset, int opts)
|
pfctl_show_tables(const char *anchor, int opts)
|
||||||
{
|
{
|
||||||
return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, ruleset, opts);
|
return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pfctl_command_tables(int argc, char *argv[], char *tname,
|
pfctl_command_tables(int argc, char *argv[], char *tname,
|
||||||
const char *command, char *file, const char *anchor, const char *ruleset,
|
const char *command, char *file, const char *anchor, int opts)
|
||||||
int opts)
|
|
||||||
{
|
{
|
||||||
if (tname == NULL || command == NULL)
|
if (tname == NULL || command == NULL)
|
||||||
usage();
|
usage();
|
||||||
return pfctl_table(argc, argv, tname, command, file, anchor, ruleset,
|
return pfctl_table(argc, argv, tname, command, file, anchor, opts);
|
||||||
opts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
||||||
char *file, const char *anchor, const char *ruleset, int opts)
|
char *file, const char *anchor, int opts)
|
||||||
{
|
{
|
||||||
struct pfr_table table;
|
struct pfr_table table;
|
||||||
struct pfr_buffer b, b2;
|
struct pfr_buffer b, b2;
|
||||||
@ -155,9 +152,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
|||||||
errx(1, "pfctl_table: strlcpy");
|
errx(1, "pfctl_table: strlcpy");
|
||||||
}
|
}
|
||||||
if (strlcpy(table.pfrt_anchor, anchor,
|
if (strlcpy(table.pfrt_anchor, anchor,
|
||||||
sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor) ||
|
sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor))
|
||||||
strlcpy(table.pfrt_ruleset, ruleset,
|
|
||||||
sizeof(table.pfrt_ruleset)) >= sizeof(table.pfrt_ruleset))
|
|
||||||
errx(1, "pfctl_table: strlcpy");
|
errx(1, "pfctl_table: strlcpy");
|
||||||
|
|
||||||
if (!strcmp(command, "-F")) {
|
if (!strcmp(command, "-F")) {
|
||||||
@ -347,8 +342,6 @@ print_table(struct pfr_table *ta, int verbose, int debug)
|
|||||||
ta->pfrt_name);
|
ta->pfrt_name);
|
||||||
if (ta->pfrt_anchor[0])
|
if (ta->pfrt_anchor[0])
|
||||||
printf("\t%s", ta->pfrt_anchor);
|
printf("\t%s", ta->pfrt_anchor);
|
||||||
if (ta->pfrt_ruleset[0])
|
|
||||||
printf(":%s", ta->pfrt_ruleset);
|
|
||||||
puts("");
|
puts("");
|
||||||
} else
|
} else
|
||||||
puts(ta->pfrt_name);
|
puts(ta->pfrt_name);
|
||||||
@ -466,16 +459,14 @@ radix_perror(void)
|
|||||||
|
|
||||||
int
|
int
|
||||||
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
||||||
const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket)
|
struct pfr_buffer *ab, u_int32_t ticket)
|
||||||
{
|
{
|
||||||
struct pfr_table tbl;
|
struct pfr_table tbl;
|
||||||
|
|
||||||
bzero(&tbl, sizeof(tbl));
|
bzero(&tbl, sizeof(tbl));
|
||||||
if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >=
|
if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >=
|
||||||
sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor,
|
sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor,
|
||||||
sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor) ||
|
sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor))
|
||||||
strlcpy(tbl.pfrt_ruleset, ruleset, sizeof(tbl.pfrt_ruleset)) >=
|
|
||||||
sizeof(tbl.pfrt_ruleset))
|
|
||||||
errx(1, "pfctl_define_table: strlcpy");
|
errx(1, "pfctl_define_table: strlcpy");
|
||||||
tbl.pfrt_flags = flags;
|
tbl.pfrt_flags = flags;
|
||||||
|
|
||||||
@ -589,7 +580,8 @@ print_iface(struct pfi_if *p, int opts)
|
|||||||
oprintf(flags, PFI_IFLAG_GROUP, "group", &first, 0);
|
oprintf(flags, PFI_IFLAG_GROUP, "group", &first, 0);
|
||||||
oprintf(flags, PFI_IFLAG_CLONABLE, "clonable", &first, 0);
|
oprintf(flags, PFI_IFLAG_CLONABLE, "clonable", &first, 0);
|
||||||
oprintf(flags, PFI_IFLAG_DYNAMIC, "dynamic", &first, 0);
|
oprintf(flags, PFI_IFLAG_DYNAMIC, "dynamic", &first, 0);
|
||||||
oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 1);
|
oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 0);
|
||||||
|
oprintf(flags, PFI_IFLAG_SKIP, "skipped", &first, 1);
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
first = 1;
|
first = 1;
|
||||||
oprintf(flags, PFI_IFLAG_PLACEHOLDER, "placeholder", &first, 1);
|
oprintf(flags, PFI_IFLAG_PLACEHOLDER, "placeholder", &first, 1);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pflogd.c,v 1.27 2004/02/13 19:01:57 otto Exp $ */
|
/* $OpenBSD: pflogd.c,v 1.33 2005/02/09 12:09:30 henning Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Theo de Raadt
|
* Copyright (c) 2001 Theo de Raadt
|
||||||
@ -271,16 +271,19 @@ reset_dump(void)
|
|||||||
fp = fdopen(fd, "a+");
|
fp = fdopen(fd, "a+");
|
||||||
|
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
|
close(fd);
|
||||||
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
if (fstat(fileno(fp), &st) == -1) {
|
if (fstat(fileno(fp), &st) == -1) {
|
||||||
|
fclose(fp);
|
||||||
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set FILE unbuffered, we do our own buffering */
|
/* set FILE unbuffered, we do our own buffering */
|
||||||
if (setvbuf(fp, NULL, _IONBF, 0)) {
|
if (setvbuf(fp, NULL, _IONBF, 0)) {
|
||||||
|
fclose(fp);
|
||||||
logmsg(LOG_ERR, "Failed to set output buffers");
|
logmsg(LOG_ERR, "Failed to set output buffers");
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
@ -291,6 +294,7 @@ reset_dump(void)
|
|||||||
if (snaplen != cur_snaplen) {
|
if (snaplen != cur_snaplen) {
|
||||||
logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
|
logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
|
||||||
if (set_snaplen(snaplen)) {
|
if (set_snaplen(snaplen)) {
|
||||||
|
fclose(fp);
|
||||||
logmsg(LOG_WARNING,
|
logmsg(LOG_WARNING,
|
||||||
"Failed, using old settings");
|
"Failed, using old settings");
|
||||||
}
|
}
|
||||||
@ -418,8 +422,9 @@ dump_packet_nobuf(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
|
|||||||
#else
|
#else
|
||||||
if (fwrite((char *)h, sizeof(*h), 1, f) != 1) {
|
if (fwrite((char *)h, sizeof(*h), 1, f) != 1) {
|
||||||
#endif
|
#endif
|
||||||
/* try to undo header to prevent corruption */
|
|
||||||
off_t pos = ftello(f);
|
off_t pos = ftello(f);
|
||||||
|
|
||||||
|
/* try to undo header to prevent corruption */
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
if (pos < sizeof(sh) ||
|
if (pos < sizeof(sh) ||
|
||||||
ftruncate(fileno(f), pos - sizeof(sh))) {
|
ftruncate(fileno(f), pos - sizeof(sh))) {
|
||||||
@ -554,6 +559,7 @@ main(int argc, char **argv)
|
|||||||
struct pcap_stat pstat;
|
struct pcap_stat pstat;
|
||||||
int ch, np, Xflag = 0;
|
int ch, np, Xflag = 0;
|
||||||
pcap_handler phandler = dump_packet;
|
pcap_handler phandler = dump_packet;
|
||||||
|
char *errstr = NULL;
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
/* another ?paranoid? safety measure we do not have */
|
/* another ?paranoid? safety measure we do not have */
|
||||||
@ -567,19 +573,35 @@ main(int argc, char **argv)
|
|||||||
Debug = 1;
|
Debug = 1;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
delay = atoi(optarg);
|
#ifdef __OpenBSD__
|
||||||
if (delay < 5 || delay > 60*60)
|
delay = strtonum(optarg, 5, 60*60, &errstr);
|
||||||
|
if (errstr)
|
||||||
|
#else
|
||||||
|
delay = strtol(optarg, &errstr, 10);
|
||||||
|
if ((delay < 5) || (delay > 60*60) ||
|
||||||
|
((errstr != NULL) && (*errstr != '\0')))
|
||||||
|
#endif
|
||||||
usage();
|
usage();
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
filename = optarg;
|
filename = optarg;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
snaplen = atoi(optarg);
|
#ifdef __OpenBSD__
|
||||||
|
snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
|
||||||
|
&errstr);
|
||||||
if (snaplen <= 0)
|
if (snaplen <= 0)
|
||||||
snaplen = DEF_SNAPLEN;
|
snaplen = DEF_SNAPLEN;
|
||||||
if (snaplen > PFLOGD_MAXSNAPLEN)
|
if (errstr)
|
||||||
snaplen = PFLOGD_MAXSNAPLEN;
|
snaplen = PFLOGD_MAXSNAPLEN;
|
||||||
|
#else
|
||||||
|
snaplen = strtol(optarg, &errstr, 10);
|
||||||
|
if (snaplen <= 0)
|
||||||
|
snaplen = DEF_SNAPLEN;
|
||||||
|
if ((snaplen > PFLOGD_MAXSNAPLEN) ||
|
||||||
|
((errstr != NULL) && (*errstr != '\0')))
|
||||||
|
snaplen = PFLOGD_MAXSNAPLEN;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
Xflag++;
|
Xflag++;
|
||||||
@ -603,6 +625,7 @@ main(int argc, char **argv)
|
|||||||
pidfile(NULL);
|
pidfile(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tzset();
|
||||||
(void)umask(S_IRWXG | S_IRWXO);
|
(void)umask(S_IRWXG | S_IRWXO);
|
||||||
|
|
||||||
/* filter will be used by the privileged process */
|
/* filter will be used by the privileged process */
|
||||||
@ -655,7 +678,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
np = pcap_dispatch(hpcap, PCAP_NUM_PKTS,
|
np = pcap_dispatch(hpcap, PCAP_NUM_PKTS,
|
||||||
dump_packet, (u_char *)dpcap);
|
phandler, (u_char *)dpcap);
|
||||||
if (np < 0) {
|
if (np < 0) {
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
if (errno == ENXIO) {
|
if (errno == ENXIO) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: privsep.c,v 1.8 2004/03/14 19:17:05 otto Exp $ */
|
/* $OpenBSD: privsep.c,v 1.13 2004/12/22 09:21:02 otto Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003 Can Erkin Acar
|
* Copyright (c) 2003 Can Erkin Acar
|
||||||
@ -69,7 +69,7 @@ int
|
|||||||
priv_init(void)
|
priv_init(void)
|
||||||
{
|
{
|
||||||
int i, fd, socks[2], cmd;
|
int i, fd, socks[2], cmd;
|
||||||
int snaplen, ret;
|
int snaplen, ret, olderrno;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
@ -118,10 +118,12 @@ priv_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Father */
|
/* Father */
|
||||||
/* Pass ALRM/TERM/HUP through to child, and accept CHLD */
|
/* Pass ALRM/TERM/HUP/INT/QUIT through to child, and accept CHLD */
|
||||||
signal(SIGALRM, sig_pass_to_chld);
|
signal(SIGALRM, sig_pass_to_chld);
|
||||||
signal(SIGTERM, sig_pass_to_chld);
|
signal(SIGTERM, sig_pass_to_chld);
|
||||||
signal(SIGHUP, sig_pass_to_chld);
|
signal(SIGHUP, sig_pass_to_chld);
|
||||||
|
signal(SIGINT, sig_pass_to_chld);
|
||||||
|
signal(SIGQUIT, sig_pass_to_chld);
|
||||||
signal(SIGCHLD, sig_chld);
|
signal(SIGCHLD, sig_chld);
|
||||||
|
|
||||||
setproctitle("[priv]");
|
setproctitle("[priv]");
|
||||||
@ -153,12 +155,14 @@ priv_init(void)
|
|||||||
fd = open(filename,
|
fd = open(filename,
|
||||||
O_RDWR|O_CREAT|O_APPEND|O_NONBLOCK|O_NOFOLLOW,
|
O_RDWR|O_CREAT|O_APPEND|O_NONBLOCK|O_NOFOLLOW,
|
||||||
0600);
|
0600);
|
||||||
|
olderrno = errno;
|
||||||
|
send_fd(socks[0], fd);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
logmsg(LOG_NOTICE,
|
logmsg(LOG_NOTICE,
|
||||||
"[priv]: failed to open %s: %s",
|
"[priv]: failed to open %s: %s",
|
||||||
filename, strerror(errno));
|
filename, strerror(olderrno));
|
||||||
send_fd(socks[0], fd);
|
else
|
||||||
close(fd);
|
close(fd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -217,7 +221,7 @@ priv_open_log(void)
|
|||||||
int cmd, fd;
|
int cmd, fd;
|
||||||
|
|
||||||
if (priv_fd < 0)
|
if (priv_fd < 0)
|
||||||
errx(1, "%s: called from privileged portion\n", __func__);
|
errx(1, "%s: called from privileged portion", __func__);
|
||||||
|
|
||||||
cmd = PRIV_OPEN_LOG;
|
cmd = PRIV_OPEN_LOG;
|
||||||
must_write(priv_fd, &cmd, sizeof(int));
|
must_write(priv_fd, &cmd, sizeof(int));
|
||||||
|
Loading…
Reference in New Issue
Block a user