diff options
author | Fernando Fernandez Mancera <ffmancera@riseup.net> | 2019-06-22 19:12:08 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-07-17 10:22:39 +0200 |
commit | 1188a69604c3df2a63daca9e735fdb535e8f6b63 (patch) | |
tree | 21887d78f5b30023546f40da96aaa4cf256a59e5 | |
parent | 82cc676289803cfd1e69dfeaa4658d57a1547a86 (diff) |
src: introduce SYNPROXY matching
Add support for "synproxy" statement. For example (for TCP port 8888):
table ip x {
chain y {
type filter hook prerouting priority raw; policy accept;
tcp dport 8888 tcp flags syn notrack
}
chain z {
type filter hook input priority filter; policy accept;
tcp dport 8888 ct state invalid,untracked synproxy mss 1460 wscale 7 timestamp sack-perm
ct state invalid drop
}
}
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | doc/statements.txt | 87 | ||||
-rw-r--r-- | include/json.h | 1 | ||||
-rw-r--r-- | include/linux/netfilter/nf_synproxy.h | 23 | ||||
-rw-r--r-- | include/linux/netfilter/nf_tables.h | 17 | ||||
-rw-r--r-- | include/statement.h | 11 | ||||
-rw-r--r-- | src/evaluate.c | 15 | ||||
-rw-r--r-- | src/json.c | 29 | ||||
-rw-r--r-- | src/netlink_delinearize.c | 17 | ||||
-rw-r--r-- | src/netlink_linearize.c | 17 | ||||
-rw-r--r-- | src/parser_bison.y | 47 | ||||
-rw-r--r-- | src/parser_json.c | 94 | ||||
-rw-r--r-- | src/scanner.l | 5 | ||||
-rw-r--r-- | src/statement.c | 51 | ||||
-rw-r--r-- | tests/py/inet/synproxy.t | 13 | ||||
-rw-r--r-- | tests/py/inet/synproxy.t.json | 71 | ||||
-rw-r--r-- | tests/py/inet/synproxy.t.payload | 72 |
16 files changed, 570 insertions, 0 deletions
diff --git a/doc/statements.txt b/doc/statements.txt index bc2f9449..e17068a8 100644 --- a/doc/statements.txt +++ b/doc/statements.txt @@ -483,6 +483,93 @@ table inet x { } ------------------------------------- +SYNPROXY STATEMENT +~~~~~~~~~~~~~~~~~~ +This statement will process TCP three-way-handshake parallel in netfilter +context to protect either local or backend system. This statement requires +connection tracking because sequence numbers need to be translated. + +[verse] +*synproxy* [*mss* 'mss_value'] [*wscale* 'wscale_value'] ['SYNPROXY_FLAGS'] + +.synproxy statement attributes +[options="header"] +|================= +| Name | Description +| mss | Maximum segment size announced to clients. This must match the backend. +| wscale | Window scale announced to clients. This must match the backend. +|================= + +.synproxy statement flags +[options="header"] +|================= +| Flag | Description +| sack-perm | +Pass client selective acknowledgement option to backend (will be disabled if +not present). +| timestamp | +Pass client timestamp option to backend (will be disabled if not present, also +needed for selective acknowledgement and window scaling). +|================= + +.Example ruleset for synproxy statement +--------------------------------------- +Determine tcp options used by backend, from an external system + + tcpdump -pni eth0 -c 1 'tcp[tcpflags] == (tcp-syn|tcp-ack)' + port 80 & + telnet 192.0.2.42 80 + 18:57:24.693307 IP 192.0.2.42.80 > 192.0.2.43.48757: + Flags [S.], seq 360414582, ack 788841994, win 14480, + options [mss 1460,sackOK, + TS val 1409056151 ecr 9690221, + nop,wscale 9], + length 0 + +Switch tcp_loose mode off, so conntrack will mark out-of-flow packets as state INVALID. + + echo 0 > /proc/sys/net/netfilter/nf_conntrack_tcp_loose + +Make SYN packets untracked. + + table ip x { + chain y { + type filter hook prerouting priority raw; policy accept; + tcp flags syn notrack + } + } + +Catch UNTRACKED (SYN packets) and INVALID (3WHS ACK packets) states and send +them to SYNPROXY. This rule will respond to SYN packets with SYN+ACK +syncookies, create ESTABLISHED for valid client response (3WHS ACK packets) and +drop incorrect cookies. Flags combinations not expected during 3WHS will not +match and continue (e.g. SYN+FIN, SYN+ACK). Finally, drop invalid packets, this +will be out-of-flow packets that were not matched by SYNPROXY. + + table ip foo { + chain z { + type filter hook input priority filter; policy accept; + ct state { invalid, untracked } synproxy mss 1460 wscale 9 timestamp sack-perm + ct state invalid drop + } + } + +The outcome ruleset of the steps above should be similar to the one below. + + table ip x { + chain y { + type filter hook prerouting priority raw; policy accept; + tcp flags syn notrack + } + + chain z { + type filter hook input priority filter; policy accept; + ct state { invalid, untracked } synproxy mss 1460 wscale 9 timestamp sack-perm + ct state invalid drop + } + } +--------------------------------------- + FLOW STATEMENT ~~~~~~~~~~~~~~ A flow statement allows us to select what flows you want to accelerate diff --git a/include/json.h b/include/json.h index c724c299..ce57c9f7 100644 --- a/include/json.h +++ b/include/json.h @@ -83,6 +83,7 @@ json_t *queue_stmt_json(const struct stmt *stmt, struct output_ctx *octx); json_t *verdict_stmt_json(const struct stmt *stmt, struct output_ctx *octx); json_t *connlimit_stmt_json(const struct stmt *stmt, struct output_ctx *octx); json_t *tproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx); +json_t *synproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx); int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd); diff --git a/include/linux/netfilter/nf_synproxy.h b/include/linux/netfilter/nf_synproxy.h new file mode 100644 index 00000000..0e7c3919 --- /dev/null +++ b/include/linux/netfilter/nf_synproxy.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _NF_SYNPROXY_H +#define _NF_SYNPROXY_H + +#include <linux/types.h> + +#define NF_SYNPROXY_OPT_MSS 0x01 +#define NF_SYNPROXY_OPT_WSCALE 0x02 +#define NF_SYNPROXY_OPT_SACK_PERM 0x04 +#define NF_SYNPROXY_OPT_TIMESTAMP 0x08 +#define NF_SYNPROXY_OPT_ECN 0x10 +#define NF_SYNPROXY_FLAGMASK (NF_SYNPROXY_OPT_MSS | \ + NF_SYNPROXY_OPT_WSCALE | \ + NF_SYNPROXY_OPT_SACK_PERM | \ + NF_SYNPROXY_OPT_TIMESTAMP) + +struct nf_synproxy_info { + __u8 options; + __u8 wscale; + __u16 mss; +}; + +#endif /* _NF_SYNPROXY_H */ diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index 709fbc8d..adc08935 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -1544,6 +1544,23 @@ enum nft_osf_attributes { #define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1) /** + * enum nft_synproxy_attributes - nftables synproxy expression + * netlink attributes + * + * @NFTA_SYNPROXY_MSS: mss value sent to the backend (NLA_U16) + * @NFTA_SYNPROXY_WSCALE: wscale value sent to the backend (NLA_U8) + * @NFTA_SYNPROXY_FLAGS: flags (NLA_U32) + */ +enum nft_synproxy_attributes { + NFTA_SYNPROXY_UNSPEC, + NFTA_SYNPROXY_MSS, + NFTA_SYNPROXY_WSCALE, + NFTA_SYNPROXY_FLAGS, + __NFTA_SYNPROXY_MAX, +}; +#define NFTA_SYNPROXY_MAX (__NFTA_SYNPROXY_MAX - 1) + +/** * enum nft_device_attributes - nf_tables device netlink attributes * * @NFTA_DEVICE_NAME: name of this device (NLA_STRING) diff --git a/include/statement.h b/include/statement.h index 6fb5cf15..585908de 100644 --- a/include/statement.h +++ b/include/statement.h @@ -204,6 +204,14 @@ struct map_stmt { extern struct stmt *map_stmt_alloc(const struct location *loc); +struct synproxy_stmt { + uint16_t mss; + uint8_t wscale; + uint32_t flags; +}; + +extern struct stmt *synproxy_stmt_alloc(const struct location *loc); + struct meter_stmt { struct expr *set; struct expr *key; @@ -271,6 +279,7 @@ extern struct stmt *xt_stmt_alloc(const struct location *loc); * @STMT_FLOW_OFFLOAD: flow offload statement * @STMT_CONNLIMIT: connection limit statement * @STMT_MAP: map statement + * @STMT_SYNPROXY: synproxy statement */ enum stmt_types { STMT_INVALID, @@ -298,6 +307,7 @@ enum stmt_types { STMT_FLOW_OFFLOAD, STMT_CONNLIMIT, STMT_MAP, + STMT_SYNPROXY, }; /** @@ -362,6 +372,7 @@ struct stmt { struct objref_stmt objref; struct flow_stmt flow; struct map_stmt map; + struct synproxy_stmt synproxy; }; }; diff --git a/src/evaluate.c b/src/evaluate.c index 864d3daf..55cd9d00 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -17,6 +17,7 @@ #include <linux/netfilter.h> #include <linux/netfilter_arp.h> #include <linux/netfilter/nf_tables.h> +#include <linux/netfilter/nf_synproxy.h> #include <linux/netfilter_ipv4.h> #include <netinet/ip_icmp.h> #include <netinet/icmp6.h> @@ -2746,6 +2747,18 @@ static int stmt_evaluate_tproxy(struct eval_ctx *ctx, struct stmt *stmt) return 0; } +static int stmt_evaluate_synproxy(struct eval_ctx *ctx, struct stmt *stmt) +{ + if (stmt->synproxy.flags != 0 && + !(stmt->synproxy.flags & (NF_SYNPROXY_OPT_MSS | + NF_SYNPROXY_OPT_WSCALE | + NF_SYNPROXY_OPT_TIMESTAMP | + NF_SYNPROXY_OPT_SACK_PERM))) + return stmt_error(ctx, stmt, "This flags are not supported for SYNPROXY"); + + return 0; +} + static int stmt_evaluate_dup(struct eval_ctx *ctx, struct stmt *stmt) { int err; @@ -3090,6 +3103,8 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt) return stmt_evaluate_objref(ctx, stmt); case STMT_MAP: return stmt_evaluate_map(ctx, stmt); + case STMT_SYNPROXY: + return stmt_evaluate_synproxy(ctx, stmt); default: BUG("unknown statement type %s\n", stmt->ops->name); } @@ -16,6 +16,7 @@ #include <linux/netfilter/nf_log.h> #include <linux/netfilter/nf_nat.h> #include <linux/netfilter/nf_tables.h> +#include <linux/netfilter/nf_synproxy.h> #include <linux/xfrm.h> #include <pwd.h> #include <grp.h> @@ -1466,6 +1467,34 @@ json_t *tproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx) return json_pack("{s:o}", "tproxy", root); } +json_t *synproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx) +{ + json_t *root = json_object(), *flags = json_array(); + + if (stmt->synproxy.flags & NF_SYNPROXY_OPT_MSS) + json_object_set_new(root, "mss", + json_integer(stmt->synproxy.mss)); + if (stmt->synproxy.flags & NF_SYNPROXY_OPT_WSCALE) + json_object_set_new(root, "wscale", + json_integer(stmt->synproxy.wscale)); + if (stmt->synproxy.flags & NF_SYNPROXY_OPT_TIMESTAMP) + json_array_append_new(flags, json_string("timestamp")); + if (stmt->synproxy.flags & NF_SYNPROXY_OPT_SACK_PERM) + json_array_append_new(flags, json_string("sack-perm")); + + if (json_array_size(flags) > 0) + json_object_set_new(root, "flags", flags); + else + json_decref(flags); + + if (!json_object_size(root)) { + json_decref(root); + root = json_null(); + } + + return json_pack("{s:o}", "synproxy", root); +} + static json_t *table_print_json_full(struct netlink_ctx *ctx, struct table *table) { diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 1dd3ffd1..fc2574b1 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -1010,6 +1010,22 @@ out_err: xfree(stmt); } +static void netlink_parse_synproxy(struct netlink_parse_ctx *ctx, + const struct location *loc, + const struct nftnl_expr *nle) +{ + struct stmt *stmt; + + stmt = synproxy_stmt_alloc(loc); + stmt->synproxy.mss = nftnl_expr_get_u16(nle, NFTNL_EXPR_SYNPROXY_MSS); + stmt->synproxy.wscale = nftnl_expr_get_u8(nle, + NFTNL_EXPR_SYNPROXY_WSCALE); + stmt->synproxy.flags = nftnl_expr_get_u32(nle, + NFTNL_EXPR_SYNPROXY_FLAGS); + + ctx->stmt = stmt; +} + static void netlink_parse_tproxy(struct netlink_parse_ctx *ctx, const struct location *loc, const struct nftnl_expr *nle) @@ -1476,6 +1492,7 @@ static const struct { { .name = "tcpopt", .parse = netlink_parse_exthdr }, { .name = "flow_offload", .parse = netlink_parse_flow_offload }, { .name = "xfrm", .parse = netlink_parse_xfrm }, + { .name = "synproxy", .parse = netlink_parse_synproxy }, }; static int netlink_parse_expr(const struct nftnl_expr *nle, diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index 2c6aa64d..498326d0 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -1141,6 +1141,21 @@ static void netlink_gen_tproxy_stmt(struct netlink_linearize_ctx *ctx, nftnl_rule_add_expr(ctx->nlr, nle); } +static void netlink_gen_synproxy_stmt(struct netlink_linearize_ctx *ctx, + const struct stmt *stmt) +{ + struct nftnl_expr *nle; + + nle = alloc_nft_expr("synproxy"); + nftnl_expr_set_u16(nle, NFTNL_EXPR_SYNPROXY_MSS, stmt->synproxy.mss); + nftnl_expr_set_u8(nle, NFTNL_EXPR_SYNPROXY_WSCALE, + stmt->synproxy.wscale); + nftnl_expr_set_u32(nle, NFTNL_EXPR_SYNPROXY_FLAGS, + stmt->synproxy.flags); + + nftnl_rule_add_expr(ctx->nlr, nle); +} + static void netlink_gen_dup_stmt(struct netlink_linearize_ctx *ctx, const struct stmt *stmt) { @@ -1382,6 +1397,8 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx, return netlink_gen_nat_stmt(ctx, stmt); case STMT_TPROXY: return netlink_gen_tproxy_stmt(ctx, stmt); + case STMT_SYNPROXY: + return netlink_gen_synproxy_stmt(ctx, stmt); case STMT_DUP: return netlink_gen_dup_stmt(ctx, stmt); case STMT_QUEUE: diff --git a/src/parser_bison.y b/src/parser_bison.y index c7591bc2..53e66952 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -23,6 +23,7 @@ #include <linux/netfilter/nf_nat.h> #include <linux/netfilter/nf_log.h> #include <linux/netfilter/nfnetlink_osf.h> +#include <linux/netfilter/nf_synproxy.h> #include <linux/xfrm.h> #include <netinet/ip_icmp.h> #include <netinet/icmp6.h> @@ -200,6 +201,11 @@ int nft_lex(void *, void *, void *); %token OSF "osf" +%token SYNPROXY "synproxy" +%token MSS "mss" +%token WSCALE "wscale" +%token SACKPERM "sack-perm" + %token HOOK "hook" %token DEVICE "device" %token DEVICES "devices" @@ -611,6 +617,9 @@ int nft_lex(void *, void *, void *); %type <val> nf_nat_flags nf_nat_flag offset_opt %type <stmt> tproxy_stmt %destructor { stmt_free($$); } tproxy_stmt +%type <stmt> synproxy_stmt synproxy_stmt_alloc +%destructor { stmt_free($$); } synproxy_stmt synproxy_stmt_alloc + %type <stmt> queue_stmt queue_stmt_alloc %destructor { stmt_free($$); } queue_stmt queue_stmt_alloc @@ -2289,6 +2298,7 @@ stmt : verdict_stmt | fwd_stmt | set_stmt | map_stmt + | synproxy_stmt ; verdict_stmt : verdict_expr @@ -2719,6 +2729,43 @@ tproxy_stmt : TPROXY TO stmt_expr } ; +synproxy_stmt : synproxy_stmt_alloc + | synproxy_stmt_alloc synproxy_args + ; + +synproxy_stmt_alloc : SYNPROXY + { + $$ = synproxy_stmt_alloc(&@$); + } + ; + +synproxy_args : synproxy_arg + { + $<stmt>$ = $<stmt>0; + } + | synproxy_args synproxy_arg + ; + +synproxy_arg : MSS NUM + { + $<stmt>0->synproxy.mss = $2; + $<stmt>0->synproxy.flags |= NF_SYNPROXY_OPT_MSS; + } + | WSCALE NUM + { + $<stmt>0->synproxy.wscale = $2; + $<stmt>0->synproxy.flags |= NF_SYNPROXY_OPT_WSCALE; + } + | TIMESTAMP + { + $<stmt>0->synproxy.flags |= NF_SYNPROXY_OPT_TIMESTAMP; + } + | SACKPERM + { + $<stmt>0->synproxy.flags |= NF_SYNPROXY_OPT_SACK_PERM; + } + ; + primary_stmt_expr : symbol_expr { $$ = $1; } | integer_expr { $$ = $1; } | boolean_expr { $$ = $1; } diff --git a/src/parser_json.c b/src/parser_json.c index 79f5865c..42893c2f 100644 --- a/src/parser_json.c +++ b/src/parser_json.c @@ -23,6 +23,7 @@ #include <linux/netfilter/nf_conntrack_tuple_common.h> #include <linux/netfilter/nf_log.h> #include <linux/netfilter/nf_nat.h> +#include <linux/netfilter/nf_synproxy.h> #include <linux/netfilter/nf_tables.h> #include <jansson.h> @@ -2180,6 +2181,98 @@ static struct stmt *json_parse_log_stmt(struct json_ctx *ctx, return stmt; } +static int json_parse_synproxy_flag(struct json_ctx *ctx, + json_t *root, int *flags) +{ + const struct { + const char *flag; + int val; + } flag_tbl[] = { + { "timestamp", NF_SYNPROXY_OPT_TIMESTAMP }, + { "sack-perm", NF_SYNPROXY_OPT_SACK_PERM }, + }; + const char *flag; + unsigned int i; + + assert(flags); + + if (!json_is_string(root)) { + json_error(ctx, "Invalid log flag type %s, expected string.", + json_typename(root)); + return 1; + } + flag = json_string_value(root); + for (i = 0; i < array_size(flag_tbl); i++) { + if (!strcmp(flag, flag_tbl[i].flag)) { + *flags |= flag_tbl[i].val; + return 0; + } + } + json_error(ctx, "Unknown log flag '%s'.", flag); + return 1; +} + +static int json_parse_synproxy_flags(struct json_ctx *ctx, json_t *root) +{ + int flags = 0; + json_t *value; + size_t index; + + if (json_is_string(root)) { + json_parse_synproxy_flag(ctx, root, &flags); + return flags; + } else if (!json_is_array(root)) { + json_error(ctx, "Invalid log flags type %s.", + json_typename(root)); + return -1; + } + json_array_foreach(root, index, value) { + if (json_parse_synproxy_flag(ctx, value, &flags)) + json_error(ctx, "Parsing log flag at index %zu failed.", + index); + } + return flags; +} + +static struct stmt *json_parse_synproxy_stmt(struct json_ctx *ctx, + const char *key, json_t *value) +{ + struct stmt *stmt; + json_t *jflags; + int tmp, flags; + + stmt = synproxy_stmt_alloc(int_loc); + + if (!json_unpack(value, "{s:i}", "mss", &tmp)) { + if (tmp < 0) { + json_error(ctx, "Invalid synproxy mss value '%d'", tmp); + stmt_free(stmt); + return NULL; + } + stmt->synproxy.mss = tmp; + stmt->synproxy.flags |= NF_SYNPROXY_OPT_MSS; + } + if (!json_unpack(value, "{s:i}", "wscale", &tmp)) { + if (tmp < 0) { + json_error(ctx, "Invalid synproxy wscale value '%d'", tmp); + stmt_free(stmt); + return NULL; + } + stmt->synproxy.wscale = tmp; + stmt->synproxy.flags |= NF_SYNPROXY_OPT_WSCALE; + } + if (!json_unpack(value, "{s:o}", "flags", &jflags)) { + flags = json_parse_synproxy_flags(ctx, jflags); + + if (flags < 0) { + stmt_free(stmt); + return NULL; + } + stmt->synproxy.flags |= flags; + } + return stmt; +} + static struct stmt *json_parse_cthelper_stmt(struct json_ctx *ctx, const char *key, json_t *value) { @@ -2375,6 +2468,7 @@ static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root) { "queue", json_parse_queue_stmt }, { "ct count", json_parse_connlimit_stmt }, { "tproxy", json_parse_tproxy_stmt }, + { "synproxy", json_parse_synproxy_stmt }, }; const char *type; unsigned int i; diff --git a/src/scanner.l b/src/scanner.l index 51bf64f4..4ed5f924 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -553,6 +553,11 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "osf" { return OSF; } +"synproxy" { return SYNPROXY; } +"mss" { return MSS; } +"wscale" { return WSCALE; } +"sack-perm" { return SACKPERM; } + "notrack" { return NOTRACK; } "options" { return OPTIONS; } diff --git a/src/statement.c b/src/statement.c index a82c1b39..a9e72de3 100644 --- a/src/statement.c +++ b/src/statement.c @@ -29,6 +29,7 @@ #include <netinet/in.h> #include <linux/netfilter/nf_nat.h> #include <linux/netfilter/nf_log.h> +#include <linux/netfilter/nf_synproxy.h> struct stmt *stmt_alloc(const struct location *loc, const struct stmt_ops *ops) @@ -883,3 +884,53 @@ struct stmt *xt_stmt_alloc(const struct location *loc) { return stmt_alloc(loc, &xt_stmt_ops); } + +static const char *synproxy_sack_to_str(const uint32_t flags) +{ + if (flags & NF_SYNPROXY_OPT_SACK_PERM) + return " sack-perm"; + + return ""; +} + +static const char *synproxy_timestamp_to_str(const uint32_t flags) +{ + if (flags & NF_SYNPROXY_OPT_TIMESTAMP) + return " timestamp"; + + return ""; +} + +static void synproxy_stmt_print(const struct stmt *stmt, + struct output_ctx *octx) +{ + uint32_t flags = stmt->synproxy.flags; + const char *ts_str = synproxy_timestamp_to_str(flags); + const char *sack_str = synproxy_sack_to_str(flags); + + if (flags & (NF_SYNPROXY_OPT_MSS | NF_SYNPROXY_OPT_WSCALE)) + nft_print(octx, "synproxy mss %u wscale %u%s%s", + stmt->synproxy.mss, stmt->synproxy.wscale, + ts_str, sack_str); + else if (flags & NF_SYNPROXY_OPT_MSS) + nft_print(octx, "synproxy mss %u%s%s", stmt->synproxy.mss, + ts_str, sack_str); + else if (flags & NF_SYNPROXY_OPT_WSCALE) + nft_print(octx, "synproxy wscale %u%s%s", stmt->synproxy.wscale, + ts_str, sack_str); + else + nft_print(octx, "synproxy%s%s", ts_str, sack_str); + +} + +static const struct stmt_ops synproxy_stmt_ops = { + .type = STMT_SYNPROXY, + .name = "synproxy", + .print = synproxy_stmt_print, + .json = synproxy_stmt_json, +}; + +struct stmt *synproxy_stmt_alloc(const struct location *loc) +{ + return stmt_alloc(loc, &synproxy_stmt_ops); +} diff --git a/tests/py/inet/synproxy.t b/tests/py/inet/synproxy.t new file mode 100644 index 00000000..55a05e1e --- /dev/null +++ b/tests/py/inet/synproxy.t @@ -0,0 +1,13 @@ +:synproxychain;type filter hook input priority 0 + +*ip;synproxyip;synproxychain +*ip6;synproxyip6;synproxychain +*inet;synproxyinet;synproxychain + +synproxy;ok +synproxy mss 1460 wscale 7;ok +synproxy mss 1460 wscale 5 timestamp sack-perm;ok +synproxy timestamp sack-perm;ok +synproxy timestamp;ok +synproxy sack-perm;ok + diff --git a/tests/py/inet/synproxy.t.json b/tests/py/inet/synproxy.t.json new file mode 100644 index 00000000..313fa9fe --- /dev/null +++ b/tests/py/inet/synproxy.t.json @@ -0,0 +1,71 @@ +# synproxy +[ + { + "synproxy":null + } +] + +# synproxy mss 1460 +[ + { + "synproxy": { + "mss": 1460 + } + } +] + +# synproxy wscale 7 +[ + { + "synproxy": { + "wscale": 7 + } + } +] + +# synproxy mss 1460 wscale 7 +[ + { + "synproxy": { + "mss": 1460, + "wscale": 7 + } + } +] + +# synproxy timestamp +[ + { + "synproxy": { + "flags": [ + "timestamp" + ] + } + } +] + +# synproxy timestamp sack-perm +[ + { + "synproxy": { + "flags": [ + "timestamp", + "sack-perm" + ] + } + } +] + +# synproxy mss 1460 wscale 7 timestamp sack-perm +[ + { + "synproxy": { + "mss": 1460, + "wscale": 7, + "flags": [ + "timestamp", + "sack-perm" + ] + } + } +] diff --git a/tests/py/inet/synproxy.t.payload b/tests/py/inet/synproxy.t.payload new file mode 100644 index 00000000..2e6feaaf --- /dev/null +++ b/tests/py/inet/synproxy.t.payload @@ -0,0 +1,72 @@ +# synproxy +ip synproxyip synproxychain + [ synproxy mss 0 wscale 0 ] + +# synproxy +ip6 synproxyip6 synproxychain + [ synproxy mss 0 wscale 0 ] + +# synproxy +inet synproxyinet synproxychain + [ synproxy mss 0 wscale 0 ] + +# synproxy mss 1460 wscale 7 +ip synproxyip synproxychain + [ synproxy mss 1460 wscale 7 ] + +# synproxy mss 1460 wscale 7 +ip6 synproxyip6 synproxychain + [ synproxy mss 1460 wscale 7 ] + +# synproxy mss 1460 wscale 7 +inet synproxyinet synproxychain + [ synproxy mss 1460 wscale 7 ] + +# synproxy mss 1460 wscale 5 timestamp sack-perm +ip synproxyip synproxychain + [ synproxy mss 1460 wscale 5 ] + +# synproxy mss 1460 wscale 5 timestamp sack-perm +ip6 synproxyip6 synproxychain + [ synproxy mss 1460 wscale 5 ] + +# synproxy mss 1460 wscale 5 timestamp sack-perm +inet synproxyinet synproxychain + [ synproxy mss 1460 wscale 5 ] + +# synproxy timestamp sack-perm +ip synproxyip synproxychain + [ synproxy mss 0 wscale 0 ] + +# synproxy timestamp sack-perm +ip6 synproxyip6 synproxychain + [ synproxy mss 0 wscale 0 ] + +# synproxy timestamp sack-perm +inet synproxyinet synproxychain + [ synproxy mss 0 wscale 0 ] + +# synproxy timestamp +ip synproxyip synproxychain + [ synproxy mss 0 wscale 0 ] + +# synproxy timestamp +ip6 synproxyip6 synproxychain + [ synproxy mss 0 wscale 0 ] + +# synproxy timestamp +inet synproxyinet synproxychain + [ synproxy mss 0 wscale 0 ] + +# synproxy sack-perm +ip synproxyip synproxychain + [ synproxy mss 0 wscale 0 ] + +# synproxy sack-perm +ip6 synproxyip6 synproxychain + [ synproxy mss 0 wscale 0 ] + +# synproxy sack-perm +inet synproxyinet synproxychain + [ synproxy mss 0 wscale 0 ] + |