Commit ac5b3c9b authored by Luc Didry's avatar Luc Didry

Allow whitelisted IPs to bypass anti-spam/bruteforce. Fix #24

parent 94d08918
Pipeline #11105 passed with stages
in 6 minutes and 10 seconds
...@@ -9,6 +9,7 @@ Revision history for Perl application Lstu ...@@ -9,6 +9,7 @@ Revision history for Perl application Lstu
- Allow to run several Lstu's instances from the same code but with - Allow to run several Lstu's instances from the same code but with
different configuration files (#23) different configuration files (#23)
- Cache dependencies for the different stages of the CI - Cache dependencies for the different stages of the CI
- Allow whitelisted IPs to bypass anti-spam/anti-bruteforce systems (#24)
0.07 Tue Dec 20 17:55:00 2016 +0100 0.07 Tue Dec 20 17:55:00 2016 +0100
- Add logo - Add logo
......
...@@ -20,6 +20,7 @@ sub startup { ...@@ -20,6 +20,7 @@ sub startup {
page_offset => 10, page_offset => 10,
theme => 'default', theme => 'default',
ban_min_strike => 3, ban_min_strike => 3,
ban_whitelist => [],
minion => { minion => {
enabled => 0, enabled => 0,
db_path => 'minion.db' db_path => 'minion.db'
......
...@@ -81,6 +81,29 @@ sub to_hash { ...@@ -81,6 +81,29 @@ sub to_hash {
}; };
} }
=head2 is_whitelisted
=over 1
=item B<Usage> : C<$c-E<gt>is_whitelisted>
=item B<Arguments> : none
=item B<Purpose> : tells you if the current object is in the configured whitelisted IPs
=item B<Returns> : boolean
=back
=cut
sub is_whitelisted {
my $c = shift;
my $ip = $c->ip;
return scalar(grep {/$ip/} @{$c->app->config('ban_whitelist')});
}
=head2 is_banned =head2 is_banned
=over 1 =over 1
...@@ -95,6 +118,8 @@ eg: C<WHERE ip = ? AND until E<gt> ? AND strike E<gt>= ?', $c->ip, time, $argume ...@@ -95,6 +118,8 @@ eg: C<WHERE ip = ? AND until E<gt> ? AND strike E<gt>= ?', $c->ip, time, $argume
=item B<Returns> : the db accessor object if the ip is banned, undef otherwise =item B<Returns> : the db accessor object if the ip is banned, undef otherwise
=item B<Info> : if the IP is whitelisted (see C<is_whitelisted> above), it must return undef
=back =back
=head2 increment_ban_delay =head2 increment_ban_delay
......
...@@ -18,6 +18,8 @@ sub is_banned { ...@@ -18,6 +18,8 @@ sub is_banned {
my $c = shift; my $c = shift;
my $ban_min_strike = shift; my $ban_min_strike = shift;
return undef if $c->is_whitelisted;
my $h = $c->app->pg->db->query('SELECT * FROM ban WHERE ip = ? AND until > ? AND strike >= ?', $c->ip, time, $ban_min_strike)->hashes; my $h = $c->app->pg->db->query('SELECT * FROM ban WHERE ip = ? AND until > ? AND strike >= ?', $c->ip, time, $ban_min_strike)->hashes;
if ($h->size) { if ($h->size) {
......
...@@ -19,6 +19,8 @@ sub is_banned { ...@@ -19,6 +19,8 @@ sub is_banned {
my $c = shift; my $c = shift;
my $ban_min_strike = shift; my $ban_min_strike = shift;
return undef if $c->is_whitelisted;
my @banned = Lstu::DB::SQLite::Ban->select('WHERE ip = ? AND until > ? AND strike >= ?', $c->ip, time, $ban_min_strike); my @banned = Lstu::DB::SQLite::Ban->select('WHERE ip = ? AND until > ? AND strike >= ?', $c->ip, time, $ban_min_strike);
if (scalar @banned) { if (scalar @banned) {
......
...@@ -115,6 +115,9 @@ sub _is_spam { ...@@ -115,6 +115,9 @@ sub _is_spam {
my $url = shift; my $url = shift;
my $nb_redir = shift; my $nb_redir = shift;
my $ip = $c->ip;
return { is_spam => 0 } if scalar(grep {/$ip/} @{$c->config('ban_whitelist')});
if ($nb_redir++ <= 2) { if ($nb_redir++ <= 2) {
my $res = check_fqdn($url->host); my $res = check_fqdn($url->host);
if (defined $res) { if (defined $res) {
......
...@@ -96,6 +96,14 @@ ...@@ -96,6 +96,14 @@
# optional, default is 3 # optional, default is 3
#ban_min_strike => 3, #ban_min_strike => 3,
# Ban whitelist
# You can whitelist IP addresses to prevent you from being banned
# Be careful, the IP addresses are compared as string, not as IP addresses
# a network range will not work
# Example of valid input: ban_whitelist => ['198.51.100.42', '2001:0DB8::42'],¬
# optional, default is an empty array
#ban_whitelist => [],
# define an URL to the Piwik instance and the ID of a website to track # define an URL to the Piwik instance and the ID of a website to track
# set if you want to track views in Piwik # set if you want to track views in Piwik
# optional, Piwik tracking is disabled by default # optional, Piwik tracking is disabled by default
......
...@@ -96,6 +96,14 @@ ...@@ -96,6 +96,14 @@
# optional, default is 3 # optional, default is 3
#ban_min_strike => 3, #ban_min_strike => 3,
# Ban whitelist
# You can whitelist IP addresses to prevent you from being banned
# Be careful, the IP addresses are compared as string, not as IP addresses
# a network range will not work
# Example of valid input: ban_whitelist => ['198.51.100.42', '2001:0DB8::42'],¬
# optional, default is an empty array
#ban_whitelist => [],
# define an URL to the Piwik instance and the ID of a website to track # define an URL to the Piwik instance and the ID of a website to track
# set if you want to track views in Piwik # set if you want to track views in Piwik
# optional, Piwik tracking is disabled by default # optional, Piwik tracking is disabled by default
......
...@@ -96,6 +96,14 @@ ...@@ -96,6 +96,14 @@
# optional, default is 3 # optional, default is 3
#ban_min_strike => 3, #ban_min_strike => 3,
# Ban whitelist
# You can whitelist IP addresses to prevent you from being banned
# Be careful, the IP addresses are compared as string, not as IP addresses
# a network range will not work
# Example of valid input: ban_whitelist => ['198.51.100.42', '2001:0DB8::42'],¬
# optional, default is an empty array
#ban_whitelist => [],
# define an URL to the Piwik instance and the ID of a website to track # define an URL to the Piwik instance and the ID of a website to track
# set if you want to track views in Piwik # set if you want to track views in Piwik
# optional, Piwik tracking is disabled by default # optional, Piwik tracking is disabled by default
......
...@@ -96,6 +96,14 @@ ...@@ -96,6 +96,14 @@
# optional, default is 3 # optional, default is 3
#ban_min_strike => 3, #ban_min_strike => 3,
# Ban whitelist
# You can whitelist IP addresses to prevent you from being banned
# Be careful, the IP addresses are compared as string, not as IP addresses
# a network range will not work
# Example of valid input: ban_whitelist => ['198.51.100.42', '2001:0DB8::42'],¬
# optional, default is an empty array
#ban_whitelist => [],
# define an URL to the Piwik instance and the ID of a website to track # define an URL to the Piwik instance and the ID of a website to track
# set if you want to track views in Piwik # set if you want to track views in Piwik
# optional, Piwik tracking is disabled by default # optional, Piwik tracking is disabled by default
......
...@@ -96,6 +96,14 @@ ...@@ -96,6 +96,14 @@
# optional, default is 3 # optional, default is 3
#ban_min_strike => 3, #ban_min_strike => 3,
# Ban whitelist
# You can whitelist IP addresses to prevent you from being banned
# Be careful, the IP addresses are compared as string, not as IP addresses
# a network range will not work
# Example of valid input: ban_whitelist => ['198.51.100.42', '2001:0DB8::42'],¬
# optional, default is an empty array
#ban_whitelist => [],
# define an URL to the Piwik instance and the ID of a website to track # define an URL to the Piwik instance and the ID of a website to track
# set if you want to track views in Piwik # set if you want to track views in Piwik
# optional, Piwik tracking is disabled by default # optional, Piwik tracking is disabled by default
......
...@@ -96,6 +96,14 @@ ...@@ -96,6 +96,14 @@
# optional, default is 3 # optional, default is 3
#ban_min_strike => 3, #ban_min_strike => 3,
# Ban whitelist
# You can whitelist IP addresses to prevent you from being banned
# Be careful, the IP addresses are compared as string, not as IP addresses
# a network range will not work
# Example of valid input: ban_whitelist => ['198.51.100.42', '2001:0DB8::42'],¬
# optional, default is an empty array
#ban_whitelist => [],
# define an URL to the Piwik instance and the ID of a website to track # define an URL to the Piwik instance and the ID of a website to track
# set if you want to track views in Piwik # set if you want to track views in Piwik
# optional, Piwik tracking is disabled by default # optional, Piwik tracking is disabled by default
......
...@@ -96,6 +96,14 @@ ...@@ -96,6 +96,14 @@
# optional, default is 3 # optional, default is 3
#ban_min_strike => 3, #ban_min_strike => 3,
# Ban whitelist
# You can whitelist IP addresses to prevent you from being banned
# Be careful, the IP addresses are compared as string, not as IP addresses
# a network range will not work
# Example of valid input: ban_whitelist => ['198.51.100.42', '2001:0DB8::42'],¬
# optional, default is an empty array
#ban_whitelist => [],
# define an URL to the Piwik instance and the ID of a website to track # define an URL to the Piwik instance and the ID of a website to track
# set if you want to track views in Piwik # set if you want to track views in Piwik
# optional, Piwik tracking is disabled by default # optional, Piwik tracking is disabled by default
......
...@@ -147,7 +147,7 @@ $t->post_ok('/a' => form => { lsturl => ' https://fiat-tux.fr', format => 'json' ...@@ -147,7 +147,7 @@ $t->post_ok('/a' => form => { lsturl => ' https://fiat-tux.fr', format => 'json'
my $config_file = Mojo::File->new($cfile->to_abs->to_string); my $config_file = Mojo::File->new($cfile->to_abs->to_string);
my $config_content = $config_file->slurp; my $config_content = $config_file->slurp;
my $config_orig = $config_content; my $config_orig = $config_content;
$config_content =~ s/#?htpasswd.*/htpasswd => 't\/lstu.passwd'/gm; $config_content =~ s/#?htpasswd.*/htpasswd => 't\/lstu.passwd',/gm;
$config_file->spurt($config_content); $config_file->spurt($config_content);
Lstu::DB::Ban->new(app => $m)->delete_all; # reset banishing Lstu::DB::Ban->new(app => $m)->delete_all; # reset banishing
...@@ -181,6 +181,25 @@ $t->get_ok('/logout') ...@@ -181,6 +181,25 @@ $t->get_ok('/logout')
->status_is(200) ->status_is(200)
->content_like(qr/You have been successfully logged out\./); ->content_like(qr/You have been successfully logged out\./);
# Test IP whitelisting
$config_content = $config_orig;
$config_content =~ s/^( +)#?ban_whitelist.*/$1ban_whitelist => ['::1', '127.0.0.1'],/gm;
$config_file->spurt($config_content);
$t = Test::Mojo->new('Lstu');
$t->ua->post('/a' => form => { lsturl => 'https://lstu.fr', format => 'json' });
$t->ua->post('/a' => form => { lsturl => 'https://lstu.fr', format => 'json' });
$t->ua->post('/a' => form => { lsturl => 'https://lstu.fr', format => 'json' });
$t->ua->post('/a' => form => { lsturl => 'https://lstu.fr', format => 'json' });
$t->ua->post('/a' => form => { lsturl => 'https://lstu.fr', format => 'json' });
$t->post_ok('/a' => form => { lsturl => 'https://lstu.fr', format => 'json' })
->status_is(200)
->json_has('url', 'short', 'success')
->json_is('/success' => true, '/url' => 'https://lstu.fr')
->json_like('/short' => qr#http://127\.0\.0\.1:\d+/[-_a-zA-Z0-9]{8}#);
$config_file->spurt($config_orig); $config_file->spurt($config_orig);
done_testing(); done_testing();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment