From 71991fae2cdd6e1cc695a9eaec7419b0bff0b542 Mon Sep 17 00:00:00 2001 From: Maksim Malchuk Date: Mon, 18 Jul 2016 23:55:49 +0300 Subject: [PATCH] SSH brute force protection for cluster This commit implements the same feature used for the Fuel master node [0] with rate-limiting requests to SSH with iptables. The protection used only when enabled and only for the not provided [1] networks. [0] I0f452c8b0a808789aa4c2cd85d1d00556b210a39 [1] I34c9907d781b81253ed6942c67b16f8480de3bb5 DocImpact Closes-Bug: #1563721 Depends-On: I7bbd96fb43fcd6030621671d0056f56324f50956 Change-Id: Id053e61ae16d126126dfb94cb4d9358dd7126d52 Co-Authored-By: Alex Schultz Signed-off-by: Maksim Malchuk --- .../manifests/firewall/firewall.pp | 47 +++++++++++++++++++ .../noop/spec/hosts/firewall/firewall_spec.rb | 14 ++++++ 2 files changed, 61 insertions(+) diff --git a/deployment/puppet/osnailyfacter/manifests/firewall/firewall.pp b/deployment/puppet/osnailyfacter/manifests/firewall/firewall.pp index cce2526e2f..ad6b79d0aa 100644 --- a/deployment/puppet/osnailyfacter/manifests/firewall/firewall.pp +++ b/deployment/puppet/osnailyfacter/manifests/firewall/firewall.pp @@ -54,6 +54,8 @@ class osnailyfacter::firewall::firewall { $pcsd_port = 2224 $rsync_port = 873 $ssh_port = 22 + $ssh_rseconds = 60 + $ssh_rhitcount = 4 $swift_account_port = 6002 $swift_container_port = 6001 $swift_object_port = 6000 @@ -124,6 +126,51 @@ class osnailyfacter::firewall::firewall { source_nets => $ssh_networks, } + $brute_force_protection = $ssh_hash['brute_force_protection'] ? { + true => 'present', + default => 'absent', + } + + firewall { '021 ssh: new pipe for a sessions': + ensure => $brute_force_protection, + proto => 'tcp', + dport => $ssh_port, + state => 'NEW', + recent => 'set', + } + + firewall { '022 ssh: more than allowed attempts logged': + ensure => $brute_force_protection, + proto => 'tcp', + dport => $ssh_port, + state => 'NEW', + recent => 'update', + rseconds => $ssh_rseconds, + rhitcount => $ssh_rhitcount, + jump => 'LOG', + log_prefix => 'iptables SSH brute-force: ', + log_level => '7', + } + + firewall { '023 ssh: block more than allowed attempts': + ensure => $brute_force_protection, + proto => 'tcp', + dport => $ssh_port, + state => 'NEW', + recent => 'update', + rseconds => $ssh_rseconds, + rhitcount => $ssh_rhitcount, + action => 'drop', + } + + firewall { '024 ssh: accept allowed new session': + ensure => $brute_force_protection, + proto => 'tcp', + dport => $ssh_port, + state => 'NEW', + action => 'accept', + } + openstack::firewall::multi_net {'109 iscsi': port => $iscsi_port, proto => 'tcp', diff --git a/tests/noop/spec/hosts/firewall/firewall_spec.rb b/tests/noop/spec/hosts/firewall/firewall_spec.rb index 14a959f34d..8f2bdc5af4 100644 --- a/tests/noop/spec/hosts/firewall/firewall_spec.rb +++ b/tests/noop/spec/hosts/firewall/firewall_spec.rb @@ -61,6 +61,14 @@ describe manifest do ssh_hash = Noop.hiera_hash 'ssh', {} + let(:ssh_brute_force) do + if ssh_hash['brute_force_protection'] + 'present' + else + 'absent' + end + end + it 'should accept connections to the SSH service only from specified networks' do if ssh_hash['security_enabled'] @@ -75,6 +83,12 @@ describe manifest do 'action' => 'accept', 'source_nets' => ssh_networks, ) + + should contain_firewall('021 ssh: new pipe for a sessions').with_ensure(ssh_brute_force) + should contain_firewall('022 ssh: more than allowed attempts logged').with_ensure(ssh_brute_force) + should contain_firewall('023 ssh: block more than allowed attempts').with_ensure(ssh_brute_force) + should contain_firewall('024 ssh: accept allowed new session').with_ensure(ssh_brute_force) + end if Noop.puppet_function 'member', roles, 'primary-controller' or Noop.puppet_function 'member', roles, 'controller'