diff --git a/miniserv.pl b/miniserv.pl index 8a106d26b..0b080e90f 100755 --- a/miniserv.pl +++ b/miniserv.pl @@ -788,6 +788,9 @@ while(1) { foreach my $ip (keys %ipconnmap) { $ipconnmap{$ip} = [ grep { $childpids{$_} } @{$ipconnmap{$ip}}]; } + foreach my $net (keys %netconnmap) { + $netconnmap{$net} = [ grep { $childpids{$_} } @{$netconnmap{$net}}]; + } # run the unblocking procedure to check if enough time has passed to # unblock hosts that never been blocked because of password failures @@ -887,12 +890,23 @@ while(1) { &get_address_ip($acptaddr, $ipv6fhs{$s}); print DEBUG "peera=$peera peerp=$peerp\n"; - # check the number of connections from this IP + # Check the number of connections from this IP $ipconnmap{$peera} ||= [ ]; $ipconns = $ipconnmap{$peera}; if ($config{'maxconns_per_ip'} >= 0 && @$ipconns > $config{'maxconns_per_ip'}) { - print STDERR "Too many connections (",scalar(@$ipconns),") from $peera\n"; + print STDERR "Too many connections (",scalar(@$ipconns),") from IP $peera\n"; + close(SOCK); + next; + } + + # Also check the number of connections from the network + ($peernet = $peera) =~ s/\.\d+$/\.0/; + $netconnmap{$peernet} ||= [ ]; + $netconns = $netconnmap{$peernet}; + if ($config{'maxconns_per_net'} >= 0 && + @$netconns > $config{'maxconns_per_net'}) { + print STDERR "Too many connections (",scalar(@$netconns),") from network $peernet\n"; close(SOCK); next; } @@ -996,6 +1010,7 @@ while(1) { } push(@childpids, $handpid); push(@$ipconns, $handpid); + push(@$netconns, $handpid); if ($need_pipes) { close($PASSINw); close($PASSOUTr); push(@passin, $PASSINr); @@ -4681,6 +4696,7 @@ my %vital = ("port", 80, "password_change", "/password_change.cgi", "maxconns", 50, "maxconns_per_ip", 25, + "maxconns_per_net", 35, "pam", "webmin", "sidname", "sid", "unauth", "^/unauthenticated/ ^/robots.txt\$ ^[A-Za-z0-9\\-/_]+\\.jar\$ ^[A-Za-z0-9\\-/_]+\\.class\$ ^[A-Za-z0-9\\-/_]+\\.gif\$ ^[A-Za-z0-9\\-/_]+\\.png\$ ^[A-Za-z0-9\\-/_]+\\.conf\$ ^[A-Za-z0-9\\-/_]+\\.ico\$ ^/robots.txt\$", diff --git a/webmin/CHANGELOG b/webmin/CHANGELOG index 03de55ea6..49cf0583a 100644 --- a/webmin/CHANGELOG +++ b/webmin/CHANGELOG @@ -145,3 +145,5 @@ Wildcard SSL certs can now be requested via Let's Encrypt in DNS mode, if the na Announcements to all Webmin users can now be displayed on the System Information page. ---- Changes since 1.940 ---- The host, port and SSL mode for redirects can now be customized via miniserv.conf options. +---- Changes since 1.960 ---- +Added options on the Ports and Addresses page to control the number of concurrent connections per IP, network and in total. diff --git a/webmin/change_bind.cgi b/webmin/change_bind.cgi index d406d77d6..cab2dbae8 100755 --- a/webmin/change_bind.cgi +++ b/webmin/change_bind.cgi @@ -114,6 +114,14 @@ else { &error($text{'bind_emaxconns_per_ip'}); $miniserv{'maxconns_per_ip'} = $in{'maxconns_per_ip'}; } +if ($in{'maxconns_per_net_def'}) { + delete($miniserv{'maxconns_per_net'}); + } +else { + $in{'maxconns_per_net'} =~ /^\d+$/ && $in{'maxconns_per_net'} > 1 || + &error($text{'bind_emaxconns_per_net'}); + $miniserv{'maxconns_per_net'} = $in{'maxconns_per_net'}; + } &put_miniserv_config(\%miniserv); &unlock_file($ENV{'MINISERV_CONFIG'}); diff --git a/webmin/edit_bind.cgi b/webmin/edit_bind.cgi index 801754088..21c3b6445 100755 --- a/webmin/edit_bind.cgi +++ b/webmin/edit_bind.cgi @@ -72,6 +72,9 @@ print &ui_table_row($text{'bind_maxconns'}, print &ui_table_row($text{'bind_maxconns_per_ip'}, &ui_opt_textbox("maxconns_per_ip", $miniserv{'maxconns_per_ip'}, 5, $text{'default'}." (25)")); +print &ui_table_row($text{'bind_maxconns_per_net'}, + &ui_opt_textbox("maxconns_per_net", $miniserv{'maxconns_per_net'}, 5, + $text{'default'}." (35)")); print &ui_table_end(); print &ui_form_end([ [ "save", $text{'save'} ] ]); diff --git a/webmin/lang/en b/webmin/lang/en index c48f9b01f..2bfbfeffd 100644 --- a/webmin/lang/en +++ b/webmin/lang/en @@ -65,8 +65,10 @@ bind_elsof=New port $1 is already in use by another process bind_eonsystem=The IP address $1 is not active on this system, and so cannot be used bind_maxconns=Maximum total concurrent connections bind_maxconns_per_ip=Maximum concurrent connections per IP +bind_maxconns_per_net=Maximum concurrent connections per network bind_emaxconns=Maximum concurrent connections must be a number greater than 1 bind_emaxconns_per_ip=Maximum concurrent connections per IP must be a number greater than 1 +bind_emaxconns_per_net=Maximum concurrent connections per network must be a number greater than 1 log_title=Logging log_desc=Webmin can be configured to write a log of web server hits, in the standard CLF log file format. If logging is enabled, you can also choose whether IP addresses or hostnames are recorded, and how often the log file is cleared. When enabled, logs are written to the file $1.