mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-05 20:26:38 +02:00
pknock: implement automatic closing
Added the optional "--autoclose" parameter (takes minutes) that closes the pknock-opened rule in a specified time. Signed-off-by: Jan Rafaj <jr+netfilter-devel@cedric.unob.cz>
This commit is contained in:

committed by
Jan Engelhardt

parent
284c0e9493
commit
9e5c2e7ee9
@@ -21,8 +21,9 @@ static const struct option pknock_mt_opts[] = {
|
||||
/* .name, .has_arg, .flag, .val */
|
||||
{.name = "knockports", .has_arg = true, .val = 'k'},
|
||||
{.name = "time", .has_arg = true, .val = 't'},
|
||||
{.name = "autoclose", .has_arg = true, .val = 'a'},
|
||||
{.name = "name", .has_arg = true, .val = 'n'},
|
||||
{.name = "opensecret", .has_arg = true, .val = 'a'},
|
||||
{.name = "opensecret", .has_arg = true, .val = 'o'},
|
||||
{.name = "closesecret", .has_arg = true, .val = 'z'},
|
||||
{.name = "strict", .has_arg = false, .val = 'x'},
|
||||
{.name = "checkip", .has_arg = false, .val = 'c'},
|
||||
@@ -36,6 +37,9 @@ static void pknock_mt_help(void)
|
||||
"Matches destination port(s).\n"
|
||||
" --time seconds\n"
|
||||
"Max allowed time between knocks.\n"
|
||||
" --autoclose minutes\n"
|
||||
"Time after which to automatically close opened\n"
|
||||
"\t\t\t\t\tport(s).\n"
|
||||
" --strict "
|
||||
"Knocks sequence must be exact.\n"
|
||||
" --name rule_name "
|
||||
@@ -106,6 +110,7 @@ __pknock_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
{
|
||||
const char *proto;
|
||||
struct xt_pknock_mtinfo *info = (void *)(*match)->data;
|
||||
unsigned int tmp;
|
||||
|
||||
switch (c) {
|
||||
case 'k': /* --knockports */
|
||||
@@ -131,6 +136,18 @@ __pknock_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
*flags |= XT_PKNOCK_TIME;
|
||||
break;
|
||||
|
||||
case 'a': /* --autoclose */
|
||||
if (*flags & XT_PKNOCK_AUTOCLOSE)
|
||||
xtables_error(PARAMETER_PROBLEM, PKNOCK
|
||||
"cannot use --autoclose twice.\n");
|
||||
if (!xtables_strtoui(optarg, NULL, &tmp, 0, ~0U))
|
||||
xtables_param_act(XTF_BAD_VALUE, PKNOCK,
|
||||
"--autoclose", optarg);
|
||||
info->autoclose_time = tmp;
|
||||
info->option |= XT_PKNOCK_AUTOCLOSE;
|
||||
*flags |= XT_PKNOCK_AUTOCLOSE;
|
||||
break;
|
||||
|
||||
case 'n': /* --name */
|
||||
if (*flags & XT_PKNOCK_NAME)
|
||||
xtables_error(PARAMETER_PROBLEM, PKNOCK
|
||||
@@ -146,7 +163,7 @@ __pknock_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'a': /* --opensecret */
|
||||
case 'o': /* --opensecret */
|
||||
if (*flags & XT_PKNOCK_OPENSECRET)
|
||||
xtables_error(PARAMETER_PROBLEM, PKNOCK
|
||||
"cannot use --opensecret twice.\n");
|
||||
@@ -236,6 +253,9 @@ static void pknock_mt_check(unsigned int flags)
|
||||
if (flags & XT_PKNOCK_TIME)
|
||||
xtables_error(PARAMETER_PROBLEM, PKNOCK
|
||||
"cannot specify --time with --checkip.\n");
|
||||
if (flags & XT_PKNOCK_AUTOCLOSE)
|
||||
xtables_error(PARAMETER_PROBLEM, PKNOCK
|
||||
"cannot specify --autoclose with --checkip.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,6 +274,8 @@ static void pknock_mt_print(const void *ip,
|
||||
}
|
||||
if (info->option & XT_PKNOCK_TIME)
|
||||
printf("time %ld ", (long)info->max_time);
|
||||
if (info->option & XT_PKNOCK_AUTOCLOSE)
|
||||
printf("autoclose %lu ", (unsigned long)info->autoclose_time);
|
||||
if (info->option & XT_PKNOCK_NAME)
|
||||
printf("name %s ", info->rule_name);
|
||||
if (info->option & XT_PKNOCK_OPENSECRET)
|
||||
@@ -279,6 +301,9 @@ static void pknock_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
}
|
||||
if (info->option & XT_PKNOCK_TIME)
|
||||
printf("--time %ld ", (long)info->max_time);
|
||||
if (info->option & XT_PKNOCK_AUTOCLOSE)
|
||||
printf("--autoclose %lu ",
|
||||
(unsigned long)info->autoclose_time);
|
||||
if (info->option & XT_PKNOCK_NAME)
|
||||
printf("--name %s ", info->rule_name);
|
||||
if (info->option & XT_PKNOCK_OPENSECRET)
|
||||
|
@@ -68,6 +68,7 @@ struct xt_pknock_rule {
|
||||
struct list_head *peer_head;
|
||||
struct proc_dir_entry *status_proc;
|
||||
unsigned long max_time;
|
||||
unsigned long autoclose_time;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -244,6 +245,7 @@ pknock_seq_show(struct seq_file *s, void *v)
|
||||
{
|
||||
const struct list_head *pos, *n;
|
||||
const struct peer *peer;
|
||||
unsigned long time;
|
||||
unsigned long expir_time;
|
||||
|
||||
const struct list_head *peer_head = v;
|
||||
@@ -264,6 +266,15 @@ pknock_seq_show(struct seq_file *s, void *v)
|
||||
seq_printf(s, "expir_time=%ld ", expir_time);
|
||||
seq_printf(s, "accepted_knock_count=%lu ",
|
||||
(unsigned long)peer->accepted_knock_count);
|
||||
if (rule->autoclose_time != 0) {
|
||||
time = 0;
|
||||
if (time_before(get_seconds(), peer->login_sec +
|
||||
rule->autoclose_time * 60))
|
||||
time = peer->login_sec +
|
||||
rule->autoclose_time * 60 -
|
||||
get_seconds();
|
||||
seq_printf(s, "autoclose_time=%lu [secs] ", time);
|
||||
}
|
||||
seq_printf(s, "\n");
|
||||
}
|
||||
|
||||
@@ -314,6 +325,19 @@ static void update_rule_timer(struct xt_pknock_rule *rule)
|
||||
add_timer(&rule->timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @peer
|
||||
* @autoclose_time
|
||||
*
|
||||
* Returns true if autoclose due, or false if still valid.
|
||||
*/
|
||||
static inline bool
|
||||
autoclose_time_passed(const struct peer *peer, unsigned int autoclose_time)
|
||||
{
|
||||
return peer != NULL && autoclose_time != 0 && time_after(get_seconds(),
|
||||
peer->login_sec + autoclose_time * 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* @peer
|
||||
* @max_time
|
||||
@@ -352,8 +376,10 @@ peer_gc(unsigned long r)
|
||||
hashtable_for_each_safe(pos, n, rule->peer_head, peer_hashsize, i) {
|
||||
peer = list_entry(pos, struct peer, head);
|
||||
|
||||
if (!has_logged_during_this_minute(peer) &&
|
||||
is_time_exceeded(peer, rule->max_time))
|
||||
if ((!has_logged_during_this_minute(peer) &&
|
||||
is_time_exceeded(peer, rule->max_time)) ||
|
||||
(peer->status == ST_ALLOWED &&
|
||||
autoclose_time_passed(peer, rule->autoclose_time)))
|
||||
{
|
||||
pk_debug("DESTROYED", peer);
|
||||
list_del(pos);
|
||||
@@ -440,9 +466,10 @@ add_rule(struct xt_pknock_mtinfo *info)
|
||||
strncpy(rule->rule_name, info->rule_name, info->rule_name_len);
|
||||
rule->rule_name_len = info->rule_name_len;
|
||||
|
||||
rule->ref_count = 1;
|
||||
rule->max_time = info->max_time;
|
||||
rule->peer_head = alloc_hashtable(peer_hashsize);
|
||||
rule->ref_count = 1;
|
||||
rule->max_time = info->max_time;
|
||||
rule->autoclose_time = info->autoclose_time;
|
||||
rule->peer_head = alloc_hashtable(peer_hashsize);
|
||||
if (rule->peer_head == NULL)
|
||||
goto out;
|
||||
|
||||
@@ -994,7 +1021,7 @@ static bool pknock_mt(const struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
goto out;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (is_first_knock(peer, info, hdr.port)) {
|
||||
@@ -1008,7 +1035,16 @@ static bool pknock_mt(const struct sk_buff *skb,
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret != 0)
|
||||
/* Handle cur.peer matching and deletion after autoclose_time passed */
|
||||
if (ret && autoclose_time_passed(peer, rule->autoclose_time)) {
|
||||
pk_debug("AUTOCLOSE TIME PASSED => BLOCKED", peer);
|
||||
ret = false;
|
||||
if (iph->protocol == IPPROTO_TCP ||
|
||||
!has_logged_during_this_minute(peer))
|
||||
remove_peer(peer);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
pk_debug("PASS OK", peer);
|
||||
spin_unlock_bh(&list_lock);
|
||||
return ret;
|
||||
@@ -1061,6 +1097,8 @@ static bool pknock_mt_check(const struct xt_mtchk_param *par)
|
||||
#endif
|
||||
if (info->option & XT_PKNOCK_TIME)
|
||||
RETURN_ERR("Can't specify --time with --checkip.\n");
|
||||
if (info->option & XT_PKNOCK_AUTOCLOSE)
|
||||
RETURN_ERR("Can't specify --autoclose with --checkip.\n");
|
||||
}
|
||||
|
||||
#ifdef PK_CRYPTO
|
||||
|
@@ -21,6 +21,7 @@ enum {
|
||||
XT_PKNOCK_CHECKIP = 1 << 4,
|
||||
XT_PKNOCK_OPENSECRET = 1 << 5,
|
||||
XT_PKNOCK_CLOSESECRET = 1 << 6,
|
||||
XT_PKNOCK_AUTOCLOSE = 1 << 7,
|
||||
|
||||
/* Can never change these, as they are make up the user protocol. */
|
||||
XT_PKNOCK_MAX_PORTS = 15,
|
||||
@@ -41,6 +42,7 @@ struct xt_pknock_mtinfo {
|
||||
uint8_t ports_count; /* number of ports */
|
||||
uint16_t port[XT_PKNOCK_MAX_PORTS]; /* port[,port,port,...] */
|
||||
uint32_t max_time; /* max matching time between ports */
|
||||
uint32_t autoclose_time;
|
||||
};
|
||||
|
||||
struct xt_pknock_nl_msg {
|
||||
|
Reference in New Issue
Block a user