bin/148686: ftp-proxy -T tag patch for FBSD
Mario Lobo
lobo at bsd.com.br
Fri Jul 16 16:10:09 UTC 2010
>Number: 148686
>Category: bin
>Synopsis: ftp-proxy -T tag patch for FBSD
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Fri Jul 16 16:10:07 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator: Mario Lobo
>Release: 8.1-PRERELEASE
>Organization:
>Environment:
FreeBSD Papi 8.1-PRERELEASE FreeBSD 8.1-PRERELEASE #0: Sat Jul 3 13:06:10 UTC 2010 root at Papi:/usr/src/sys/amd64/compile/LOBO amd64
>Description:
I felt sorry the -T tag option was present in Linux and not on FBSD because I
got to a situation where it would really be useful for me. So I decided to
stuff my hands on the grease can.
What this does is to give the option to put a tag instead of a queue, to the
dynamic rules that ftp-proxy creates on the fly. The option to put a queue is
nice but it confines the rule to THAT queue only, and you cannot create queues
with the same name on different interfaces. You could specify 2 interfaces on
the same altq rule, but then again, both interfaces will be confined to the
same queue tunings.
The -T "tag" option however, besides tagging the packets for the rule, takes
the "quick" keyword out of it, so rule processing can continue, to later find
a rule that has the keyword "tagged tag", and be sent to any queue you want. A
really welcomed flexibility.
The lines bellow were taken during an ftp session to ftp.openbsd.com from a
LAN client station.
================================
# Server [20:14:03]
[~]>pfctl -vv -sA
ftp-proxy
ftp-proxy/15780.1
# Server [20:15:01]
[~]> pfctl -vv -a ftp-proxy/15780.1 -sr
@0 pass in log inet proto tcp from 172.16.3.145 to 129.128.5.191 port = 61076
flags S/SA keep state (max 1) tag ftp_proxy rtable 0
[ Evaluations: 4 Packets: 0 Bytes: 0 States: 0
]
[ Inserted: uid 62 pid 15780 ]
@1 pass out log inet proto tcp from 189.12.120.67 to 129.128.5.191 port =
61076 flags S/SA keep state (max 1) tag ftp_proxy rtable 0
[ Evaluations: 4 Packets: 0 Bytes: 0 States: 0
]
[ Inserted: uid 62 pid 15780 ]
# Server [20:15:11]
[~]>pfctl -vv -sA
ftp-proxy
ftp-proxy/15780.1
# Server [20:15:16]
[~]> pfctl -vv -a ftp-proxy/15780.1 -sn
@0 nat inet proto tcp from 172.16.3.145 to 129.128.5.191 port = 61076 rtable 0
-> 189.12.120.67
[ Evaluations: 1 Packets: 0 Bytes: 0 States: 0
]
[ Inserted: uid 62 pid 15780 ]
@0 rdr inet proto tcp from 172.16.3.145 to 129.128.5.191 port = 51973 rtable 0
-> 129.128.5.191 port 61076
[ Evaluations: 6 Packets: 8 Bytes: 1485 States: 0
]
[ Inserted: uid 62 pid 15780 ]
# Server [20:15:23]
[~]> pfctl -vv -a ftp-proxy/15780.1 -sn
pfctl: DIOCGETRULES: Invalid argument
# Server [20:16:12]
[~]>pfctl -vv -sA
ftp-proxy
================================
The nat, rdr and pass rules are correctly created and tagged.
Observe the times to see that ftp-proxy removes the rule really fast.
To apply the patch, copy it to
/usr/src/contrib/pf/ftp-proxy/
then,
cd /usr/src/usr.sbin/ftp-proxy/ftp-proxy
make [clean]
make install
>How-To-Repeat:
NA
>Fix:
Patch attached with submission follows:
--- ftp-proxy.c.orig 2009-08-03 08:13:06.000000000 +0000
+++ ftp-proxy.c 2010-07-13 12:56:07.000000000 +0000
@@ -116,7 +116,7 @@
struct sockaddr_storage fixed_server_ss, fixed_proxy_ss;
char *fixed_server, *fixed_server_port, *fixed_proxy, *listen_ip, *listen_port,
- *qname;
+ *qname, *tname;
int anonymous_only, daemonize, id_count, ipv6_mode, loglevel, max_sessions,
rfc_mode, session_count, timeout, verbose;
extern char *__progname;
@@ -601,6 +601,7 @@
loglevel = LOG_NOTICE;
max_sessions = 100;
qname = NULL;
+ tname = NULL;
rfc_mode = 0;
timeout = 24 * 3600;
verbose = 0;
@@ -609,7 +610,7 @@
id_count = 1;
session_count = 0;
- while ((ch = getopt(argc, argv, "6Aa:b:D:dm:P:p:q:R:rt:v")) != -1) {
+ while ((ch = getopt(argc, argv, "6Aa:b:D:dm:P:p:q:R:rt:T:v")) != -1) {
switch (ch) {
case '6':
ipv6_mode = 1;
@@ -647,8 +648,9 @@
if (strlen(optarg) >= PF_QNAME_SIZE)
errx(1, "queuename too long");
qname = optarg;
+ tname = NULL;
break;
- case 'R':
+ case 'R':
fixed_server = optarg;
break;
case 'r':
@@ -659,6 +661,12 @@
if (errstr)
errx(1, "timeout %s", errstr);
break;
+ case 'T':
+ if (strlen(optarg) >= PF_TAG_NAME_SIZE)
+ errx(1, "tagname too long");
+ tname = optarg;
+ qname = NULL;
+ break;
case 'v':
verbose++;
if (verbose > 2)
@@ -734,7 +742,8 @@
freeaddrinfo(res);
/* Initialize pf. */
- init_filter(qname, verbose);
+ init_filter_q(qname, verbose);
+ init_filter_t(tname, verbose);
if (daemonize) {
if (daemon(0, 0) == -1)
@@ -1102,6 +1111,6 @@
{
fprintf(stderr, "usage: %s [-6Adrv] [-a address] [-b address]"
" [-D level] [-m maxsessions]\n [-P port]"
- " [-p port] [-q queue] [-R address] [-t timeout]\n", __progname);
+ " [-p port] [-q queue] [-R address] [-t timeout] [-T tag]\n", __progname);
exit(1);
}
--- filter.c.orig 2007-07-03 12:21:51.000000000 +0000
+++ filter.c 2010-07-13 05:57:20.000000000 +0000
@@ -54,6 +54,7 @@
static struct pfioc_trans_e pfte[TRANS_SIZE];
static int dev, rule_log;
static char *qname;
+static char *tname;
int
add_filter(u_int32_t id, u_int8_t dir, struct sockaddr *src,
@@ -159,7 +160,7 @@
}
void
-init_filter(char *opt_qname, int opt_verbose)
+init_filter_q(char *opt_qname, int opt_verbose)
{
struct pf_status status;
@@ -179,6 +180,28 @@
errx(1, "pf is disabled");
}
+void
+init_filter_t(char *opt_tname, int opt_verbose)
+{
+ struct pf_status status;
+
+ tname = opt_tname;
+
+ if (opt_verbose == 1)
+ rule_log = PF_LOG;
+ else if (opt_verbose == 2)
+ rule_log = PF_LOG_ALL;
+
+ dev = open("/dev/pf", O_RDWR);
+ if (dev == -1)
+ err(1, "/dev/pf");
+ if (ioctl(dev, DIOCGETSTATUS, &status) == -1)
+ err(1, "DIOCGETSTATUS");
+ if (!status.running)
+ errx(1, "pf is disabled");
+}
+
+
int
prepare_commit(u_int32_t id)
{
@@ -279,20 +302,29 @@
switch (rs_num) {
case PF_RULESET_FILTER:
- /*
- * pass quick [log] inet[6] proto tcp \
- * from $src to $dst port = $d_port flags S/SA keep state
- * (max 1) [queue qname]
- */
- pfr.rule.action = PF_PASS;
- pfr.rule.quick = 1;
- pfr.rule.log = rule_log;
- pfr.rule.keep_state = 1;
- pfr.rule.flags = TH_SYN;
- pfr.rule.flagset = (TH_SYN|TH_ACK);
- pfr.rule.max_states = 1;
- if (qname != NULL)
- strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname);
+
+ /*
+ * pass quick [log] inet[6] proto tcp \
+ * from $src to $dst port = $d_port flags S/SA keep state
+ * (max 1) [queue qname]
+ */
+
+ pfr.rule.action = PF_PASS;
+ pfr.rule.log = rule_log;
+ pfr.rule.keep_state = 1;
+ pfr.rule.flags = TH_SYN;
+ pfr.rule.flagset = (TH_SYN|TH_ACK);
+ pfr.rule.max_states = 1;
+ pfr.rule.quick = 1;
+
+ if (qname != NULL) {
+ strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname);
+ } else {
+ if (tname != NULL) {
+ pfr.rule.quick = 0;
+ strlcpy(pfr.rule.tagname, tname, sizeof pfr.rule.tagname);
+ }
+ }
break;
case PF_RULESET_NAT:
/*
--- filter.h.orig 2007-07-03 12:21:50.000000000 +0000
+++ filter.h 2010-07-13 05:25:52.000000000 +0000
@@ -26,6 +26,7 @@
struct sockaddr *, u_int16_t);
int do_commit(void);
int do_rollback(void);
-void init_filter(char *, int);
+void init_filter_q(char *, int);
+void init_filter_t(char *, int);
int prepare_commit(u_int32_t);
int server_lookup(struct sockaddr *, struct sockaddr *, struct sockaddr *);
--- ftp-proxy.8.orig 2009-08-03 08:13:06.000000000 +0000
+++ ftp-proxy.8 2010-07-13 13:22:58.000000000 +0000
@@ -120,7 +120,9 @@
.It Fl q Ar queue
Create rules with queue
.Ar queue
-appended, so that data connections can be queued.
+appended, so that data connections can be queued. The -T option
+is automatically cancelled. If -T and -q are both present, the
+last on the command line prevails.
.It Fl R Ar address
Fixed server address, also known as reverse mode.
The proxy will always connect to the same server, regardless of
@@ -136,6 +138,12 @@
The maximum is 86400 seconds, which is also the default.
Do not set this too low, because the control connection is usually
idle when large data transfers are taking place.
+.It Fl T Ar tag
+The filter rules will add tag
+.Ar tag
+to data connections, and not match quick. This way, alternative rules
+that use the tagged keyword can be implemented. The -q option is
+is automatically cancelled.
.It Fl v
Set the 'log' flag on pf rules committed by
.Nm .
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list