diff options
author | dan <dan@FreeBSD.org> | 2000-06-08 15:34:51 +0000 |
---|---|---|
committer | dan <dan@FreeBSD.org> | 2000-06-08 15:34:51 +0000 |
commit | c3897dad80cc844b7f75b8cfa53825c031d02605 (patch) | |
tree | a156e91e6ecec2e7ac6b722fecb49d451eb5515b /sbin/ipfw | |
parent | 31f827d91f8e4147518f8d6192a98d5196ef935a (diff) | |
download | FreeBSD-src-c3897dad80cc844b7f75b8cfa53825c031d02605.zip FreeBSD-src-c3897dad80cc844b7f75b8cfa53825c031d02605.tar.gz |
Add tcpoptions to ipfw. This works much in the same way as ipoptions do.
It also squashes 99% of packet kiddie synflood orgies. For example, to
rate syn packets without MSS,
ipfw pipe 10 config 56Kbit/s queue 10Packets
ipfw add pipe 10 tcp from any to any in setup tcpoptions !mss
Submitted by: Richard A. Steenbergen <ras@e-gerbil.net>
Diffstat (limited to 'sbin/ipfw')
-rw-r--r-- | sbin/ipfw/ipfw.8 | 19 | ||||
-rw-r--r-- | sbin/ipfw/ipfw.c | 74 |
2 files changed, 88 insertions, 5 deletions
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index b7104a8..13dde53 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -650,6 +650,25 @@ The supported IP options are: The absence of a particular option may be denoted with a .Ql ! . +.It Cm tcpoptions Ar spec +Match if the TCP header contains the comma separated list of +options specified in +.Ar spec . +The supported TCP options are: +.Pp +.Cm mss +(maximum segment size), +.Cm window +(tcp window advertisement), +.Cm sack +(selective ack), +.Cm ts +(rfc1323 timestamp) and +.Cm cc +(rfc1644 t/tcp connection count). +The absence of a particular option may be denoted +with a +.Ql ! . .It Cm established TCP packets only. Match packets that have the RST or ACK bits set. diff --git a/sbin/ipfw/ipfw.c b/sbin/ipfw/ipfw.c index 0c43203..75cb893 100644 --- a/sbin/ipfw/ipfw.c +++ b/sbin/ipfw/ipfw.c @@ -437,7 +437,7 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth) #define PRINTFLG(x) {if (_flg_printed) printf(",");\ printf(x); _flg_printed = 1;} - printf(" tcpflg "); + printf(" tcpflags "); if (chain->fw_tcpf & IP_FW_TCPF_FIN) PRINTFLG("fin"); if (chain->fw_tcpnf & IP_FW_TCPF_FIN) PRINTFLG("!fin"); if (chain->fw_tcpf & IP_FW_TCPF_SYN) PRINTFLG("syn"); @@ -451,6 +451,24 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth) if (chain->fw_tcpf & IP_FW_TCPF_URG) PRINTFLG("urg"); if (chain->fw_tcpnf & IP_FW_TCPF_URG) PRINTFLG("!urg"); } + if (chain->fw_tcpopt || chain->fw_tcpnopt) { + int _opt_printed = 0; +#define PRINTTOPT(x) {if (_opt_printed) printf(",");\ + printf(x); _opt_printed = 1;} + + printf(" tcpoptions "); + if (chain->fw_tcpopt & IP_FW_TCPOPT_MSS) PRINTTOPT("mss"); + if (chain->fw_tcpnopt & IP_FW_TCPOPT_MSS) PRINTTOPT("!mss"); + if (chain->fw_tcpopt & IP_FW_TCPOPT_WINDOW) PRINTTOPT("window"); + if (chain->fw_tcpnopt & IP_FW_TCPOPT_WINDOW) PRINTTOPT("!window"); + if (chain->fw_tcpopt & IP_FW_TCPOPT_SACK) PRINTTOPT("sack"); + if (chain->fw_tcpnopt & IP_FW_TCPOPT_SACK) PRINTTOPT("!sack"); + if (chain->fw_tcpopt & IP_FW_TCPOPT_TS) PRINTTOPT("ts"); + if (chain->fw_tcpnopt & IP_FW_TCPOPT_TS) PRINTTOPT("!ts"); + if (chain->fw_tcpopt & IP_FW_TCPOPT_CC) PRINTTOPT("cc"); + if (chain->fw_tcpnopt & IP_FW_TCPOPT_CC) PRINTTOPT("!cc"); + } + if (chain->fw_flg & IP_FW_F_ICMPBIT) { int type_index; int first = 1; @@ -818,6 +836,7 @@ show_usage(const char *fmt, ...) " {established|setup}\n" " tcpflags [!]{syn|fin|rst|ack|psh|urg},...\n" " ipoptions [!]{ssrr|lsrr|rr|ts},...\n" +" tcpoptions [!]{mss|window|sack|ts|cc},...\n" " icmptypes {type[,type]}...\n" " pipeconfig:\n" " {bw|bandwidth} <number>{bit/s|Kbit/s|Mbit/s|Bytes/s|KBytes/s|MBytes/s}\n" @@ -1025,9 +1044,7 @@ fill_port(cnt, ptr, off, arg) } static void -fill_tcpflag(set, reset, vp) - u_char *set, *reset; - char **vp; +fill_tcpflag(u_char *set, u_char *reset, char **vp) { char *p = *vp,*q; u_char *d; @@ -1067,6 +1084,45 @@ fill_tcpflag(set, reset, vp) } static void +fill_tcpopts(u_char *set, u_char *reset, char **vp) +{ + char *p = *vp,*q; + u_char *d; + + while (p && *p) { + struct tpcopts { + char * name; + u_char value; + } opts[] = { + { "mss", IP_FW_TCPOPT_MSS }, + { "window", IP_FW_TCPOPT_WINDOW }, + { "sack", IP_FW_TCPOPT_SACK }, + { "ts", IP_FW_TCPOPT_TS }, + { "cc", IP_FW_TCPOPT_CC }, + }; + int i; + + if (*p == '!') { + p++; + d = reset; + } else { + d = set; + } + q = strchr(p, ','); + if (q) + *q++ = '\0'; + for (i = 0; i < sizeof(opts) / sizeof(opts[0]); ++i) + if (!strncmp(p, opts[i].name, strlen(p))) { + *d |= opts[i].value; + break; + } + if (i == sizeof(opts) / sizeof(opts[0])) + show_usage("invalid tcp option ``%s''", p); + p = q; + } +} + +static void fill_ipopt(u_char *set, u_char *reset, char **vp) { char *p = *vp,*q; @@ -1839,7 +1895,7 @@ badviacombo: rule.fw_tcpnf |= IP_FW_TCPF_ACK; av++; ac--; continue; } - if (!strncmp(*av,"tcpflags",strlen(*av))) { + if (!strncmp(*av,"tcpflags",strlen(*av)) || !strncmp(*av,"tcpflgs",strlen(*av))) { av++; ac--; if (!ac) show_usage("missing argument" @@ -1847,6 +1903,14 @@ badviacombo: fill_tcpflag(&rule.fw_tcpf, &rule.fw_tcpnf, av); av++; ac--; continue; } + if (!strncmp(*av,"tcpoptions",strlen(*av)) || !strncmp(*av, "tcpopts",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``tcpflags''"); + fill_tcpopts(&rule.fw_tcpopt, &rule.fw_tcpnopt, av); + av++; ac--; continue; + } } if (rule.fw_prot == IPPROTO_ICMP) { if (!strncmp(*av,"icmptypes",strlen(*av))) { |