From 3fa75a081d5ae82711d4c1f3b5545b5942e9cecf Mon Sep 17 00:00:00 2001 From: Evgeniy Ivanov Date: Sat, 20 Aug 2016 16:22:14 +0300 Subject: [PATCH] new iptabes deployment #61 --- ansible.cfg | 1 + roles/common/templates/sshd_config.j2 | 2 +- roles/dns_adblocking/handlers/main.yml | 3 - roles/dns_adblocking/tasks/main.yml | 29 +--- roles/security/handlers/main.yml | 4 +- roles/security/tasks/main.yml | 221 ++++++++++++------------- roles/security/templates/rules.v4.j2 | 32 ++++ roles/security/templates/rules.v6.j2 | 43 +++++ roles/vpn/handlers/main.yml | 3 - roles/vpn/tasks/main.yml | 10 -- 10 files changed, 186 insertions(+), 162 deletions(-) create mode 100644 roles/security/templates/rules.v4.j2 create mode 100644 roles/security/templates/rules.v6.j2 diff --git a/ansible.cfg b/ansible.cfg index 4abecdf..dc8f8cd 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -9,3 +9,4 @@ record_host_keys = False [ssh_connection] ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null +scp_if_ssh = True diff --git a/roles/common/templates/sshd_config.j2 b/roles/common/templates/sshd_config.j2 index d17d9f6..8a972b5 100644 --- a/roles/common/templates/sshd_config.j2 +++ b/roles/common/templates/sshd_config.j2 @@ -81,7 +81,7 @@ TCPKeepAlive yes # Allow client to pass locale environment variables AcceptEnv LANG LC_* -# Subsystem sftp /usr/lib/openssh/sftp-server +Subsystem sftp /usr/lib/openssh/sftp-server # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will diff --git a/roles/dns_adblocking/handlers/main.yml b/roles/dns_adblocking/handlers/main.yml index 562427d..98278ce 100644 --- a/roles/dns_adblocking/handlers/main.yml +++ b/roles/dns_adblocking/handlers/main.yml @@ -3,6 +3,3 @@ - name: restart apparmor service: name=apparmor state=restarted - -- name: save iptables - command: service netfilter-persistent save diff --git a/roles/dns_adblocking/tasks/main.yml b/roles/dns_adblocking/tasks/main.yml index 8ff6ed9..aa72a4c 100644 --- a/roles/dns_adblocking/tasks/main.yml +++ b/roles/dns_adblocking/tasks/main.yml @@ -27,33 +27,6 @@ shell: > /opt/adblock.sh -- name: Forward all DNS requests to the local resolver - iptables: - table: nat - chain: PREROUTING - protocol: udp - destination_port: 53 - source: "{{ vpn_network }}" - jump: DNAT - to_destination: 172.16.0.1:53 - notify: - - save iptables - -- name: Forward all DNS requests to the local resolver - iptables: - table: nat - chain: PREROUTING - protocol: udp - destination_port: 53 - source: "{{ vpn_network_ipv6 }}" - jump: DNAT - to_destination: fcaa::1:53 - ip_version: ipv6 - notify: - - save iptables - - name: Dnsmasq enabled and started service: name=dnsmasq state=started enabled=yes - -- name: Dnsmasq disabled and stopped - service: name=dnsmasq state=stopped enabled=no + diff --git a/roles/security/handlers/main.yml b/roles/security/handlers/main.yml index 2b8e5ad..f5fb1c9 100644 --- a/roles/security/handlers/main.yml +++ b/roles/security/handlers/main.yml @@ -1,8 +1,8 @@ - name: restart rsyslog service: name=rsyslog state=restarted -- name: save iptables - command: service netfilter-persistent save +- name: restart iptables + service: name=netfilter-persistent state=restarted - name: flush routing cache shell: echo 1 > /proc/sys/net/ipv4/route/flush diff --git a/roles/security/tasks/main.yml b/roles/security/tasks/main.yml index c9ce055..9f5a665 100644 --- a/roles/security/tasks/main.yml +++ b/roles/security/tasks/main.yml @@ -1,117 +1,108 @@ -# Using a two-pass approach for checking directories in order to support symlinks. -- name: Find directories for minimizing access - stat: - path: "{{ item }}" - register: minimize_access_directories +## Using a two-pass approach for checking directories in order to support symlinks. +#- name: Find directories for minimizing access + #stat: + #path: "{{ item }}" + #register: minimize_access_directories + #with_items: + #- '/usr/local/sbin' + #- '/usr/local/bin' + #- '/usr/sbin' + #- '/usr/bin' + #- '/sbin' + #- '/bin' + +#- name: Minimize access + #file: path='{{ item.stat.path }}' mode='go-w' recurse=yes + #when: item.stat.isdir + #with_items: "{{ minimize_access_directories.results }}" + #no_log: True + +#- name: Change shadow ownership to root and mode to 0600 + #file: dest='/etc/shadow' owner=root group=root mode=0600 + +#- name: change su-binary to only be accessible to user and group root + #file: dest='/bin/su' owner=root group=root mode=0750 + +#- name: Collect Use of privileged commands + #shell: > + #/usr/bin/find {/usr/local/sbin,/usr/local/bin,/sbin,/bin,/usr/sbin,/usr/bin} -xdev \( -perm -4000 -o -perm -2000 \) -type f | awk '{print "-a always,exit -F path=" $1 " -F perm=x -F auid>=500 -F auid!=4294967295 -k privileged" }' + #args: + #executable: /bin/bash + #register: privileged_programs + +## Rsyslog + +#- name: Rsyslog configured + #template: src=rsyslog.conf.j2 dest=/etc/rsyslog.conf + #notify: + #- restart rsyslog + +#- name: Rsyslog CIS configured + #template: src=CIS.conf.j2 dest=/etc/rsyslog.d/CIS.conf owner=root group=root mode=0644 + #notify: + #- restart rsyslog + +#- name: Enable services + #service: name=rsyslog enabled=yes + +## Core dumps + +#- name: Restrict core dumps (with PAM) + #lineinfile: dest=/etc/security/limits.conf line="* hard core 0" state=present + +#- name: Restrict core dumps (with sysctl) + #sysctl: name=fs.suid_dumpable value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + +## Kernel fixes + +#- name: Disable Source Routed Packet Acceptance + #sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + #with_items: + #- net.ipv4.conf.all.accept_source_route + #- net.ipv4.conf.default.accept_source_route + #notify: + #- flush routing cache + +#- name: Disable ICMP Redirect Acceptance + #sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + #with_items: + #- net.ipv4.conf.all.accept_redirects + #- net.ipv4.conf.default.accept_redirects + +#- name: Disable Secure ICMP Redirect Acceptance + #sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + #with_items: + #- net.ipv4.conf.all.secure_redirects + #- net.ipv4.conf.default.secure_redirects + #notify: + #- flush routing cache + +#- name: Enable Bad Error Message Protection + #sysctl: name=net.ipv4.icmp_ignore_bogus_error_responses value=1 ignoreerrors=yes sysctl_set=yes reload=yes state=present + #notify: + #- flush routing cache + +#- name: Enable RFC-recommended Source Route Validation + #sysctl: name="{{item}}" value=1 ignoreerrors=yes sysctl_set=yes reload=yes state=present + #with_items: + #- net.ipv4.conf.all.rp_filter + #- net.ipv4.conf.default.rp_filter + #notify: + #- flush routing cache + +#- name: Enable packet forwarding for IPv4 + #sysctl: name=net.ipv4.ip_forward value=1 + +#- name: Enable packet forwarding for IPv6 + #sysctl: name=net.ipv6.conf.all.forwarding value=1 + +#- name: Do not send ICMP redirects (we are not a router) + #sysctl: name=net.ipv4.conf.all.send_redirects value=0 + +- name: Iptables configured + template: src="{{ item.src }}" dest="{{ item.dest }}" owner=root group=root mode=0640 with_items: - - '/usr/local/sbin' - - '/usr/local/bin' - - '/usr/sbin' - - '/usr/bin' - - '/sbin' - - '/bin' - -- name: Minimize access - file: path='{{ item.stat.path }}' mode='go-w' recurse=yes - when: item.stat.isdir - with_items: "{{ minimize_access_directories.results }}" - no_log: True - -- name: Change shadow ownership to root and mode to 0600 - file: dest='/etc/shadow' owner=root group=root mode=0600 - -- name: change su-binary to only be accessible to user and group root - file: dest='/bin/su' owner=root group=root mode=0750 - -- name: Collect Use of privileged commands - shell: > - /usr/bin/find {/usr/local/sbin,/usr/local/bin,/sbin,/bin,/usr/sbin,/usr/bin} -xdev \( -perm -4000 -o -perm -2000 \) -type f | awk '{print "-a always,exit -F path=" $1 " -F perm=x -F auid>=500 -F auid!=4294967295 -k privileged" }' - args: - executable: /bin/bash - register: privileged_programs - -# Rsyslog - -- name: Rsyslog configured - template: src=rsyslog.conf.j2 dest=/etc/rsyslog.conf + - { src: rules.v4.j2, dest: /etc/iptables/rules.v4 } + - { src: rules.v6.j2, dest: /etc/iptables/rules.v6 } notify: - - restart rsyslog - -- name: Rsyslog CIS configured - template: src=CIS.conf.j2 dest=/etc/rsyslog.d/CIS.conf owner=root group=root mode=0644 - notify: - - restart rsyslog - -- name: Enable services - service: name=rsyslog enabled=yes - -# Core dumps - -- name: Restrict core dumps (with PAM) - lineinfile: dest=/etc/security/limits.conf line="* hard core 0" state=present - -- name: Restrict core dumps (with sysctl) - sysctl: name=fs.suid_dumpable value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present - -# Kernel fixes - -- name: Disable Source Routed Packet Acceptance - sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present - with_items: - - net.ipv4.conf.all.accept_source_route - - net.ipv4.conf.default.accept_source_route - notify: - - flush routing cache - -- name: Disable ICMP Redirect Acceptance - sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present - with_items: - - net.ipv4.conf.all.accept_redirects - - net.ipv4.conf.default.accept_redirects - -- name: Disable Secure ICMP Redirect Acceptance - sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present - with_items: - - net.ipv4.conf.all.secure_redirects - - net.ipv4.conf.default.secure_redirects - notify: - - flush routing cache - -- name: Enable Bad Error Message Protection - sysctl: name=net.ipv4.icmp_ignore_bogus_error_responses value=1 ignoreerrors=yes sysctl_set=yes reload=yes state=present - notify: - - flush routing cache - -- name: Enable RFC-recommended Source Route Validation - sysctl: name="{{item}}" value=1 ignoreerrors=yes sysctl_set=yes reload=yes state=present - with_items: - - net.ipv4.conf.all.rp_filter - - net.ipv4.conf.default.rp_filter - notify: - - flush routing cache - -- name: Enable packet forwarding for IPv4 - sysctl: name=net.ipv4.ip_forward value=1 - -- name: Enable packet forwarding for IPv6 - sysctl: name=net.ipv6.conf.all.forwarding value=1 - -- name: Do not send ICMP redirects (we are not a router) - sysctl: name=net.ipv4.conf.all.send_redirects value=0 - -- name: Drop SMB traffic - iptables: - table: filter - chain: FORWARD - protocol: tcp - source: 0.0.0.0/0 - destination: 0.0.0.0/0 - destination_port: "{{ item }}" - jump: DROP - action: insert - with_items: - - 137 - - 139 - - 445 - notify: - - save iptables + - restart iptables diff --git a/roles/security/templates/rules.v4.j2 b/roles/security/templates/rules.v4.j2 new file mode 100644 index 0000000..46fbe85 --- /dev/null +++ b/roles/security/templates/rules.v4.j2 @@ -0,0 +1,32 @@ +*nat +:PREROUTING ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +{% if dns_enabled is defined and dns_enabled == "Y" %} +-A PREROUTING -s {{ vpn_network }} -p udp -m udp --dport 53 -j DNAT --to-destination 172.16.0.1:53 +{% endif %} +-A POSTROUTING -s {{ vpn_network }} -m policy --pol none --dir out -j MASQUERADE +COMMIT +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] +-A INPUT -i lo -j ACCEPT +-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A INPUT -p esp -j ACCEPT +-A INPUT -p ah -j ACCEPT +# rate limit ICMP traffic per source +-A INPUT -p icmp --icmp-type echo-request -m hashlimit --hashlimit-upto 5/s --hashlimit-mode srcip --hashlimit-srcmask 32 --hashlimit-name icmp-echo-drop -j DROP +-A INPUT -p udp -m multiport --dports 500,4500 -j ACCEPT +-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT +# TODO: +# The IP of the resolver should be bound to a DUMMY interface. +# DUMMY interfaces are the proper way to install IPs without assigning them any +# particular virtual (tun,tap,...) or physical (ethernet) interface. +-A INPUT -d 172.16.0.1 -p udp --dport 53 -j ACCEPT +-A INPUT -d 172.16.0.1 -p tcp -m multiport --dport 8080,8118 -j ACCEPT +-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -p tcp --dport 445 -j DROP +-A FORWARD -p udp -m multiport --ports 137,138 -j DROP +-A FORWARD -p tcp -m multiport --ports 137,139 -j DROP +-A FORWARD -m conntrack --ctstate NEW -s {{ vpn_network }} -m policy --pol ipsec --dir in -j ACCEPT +COMMIT diff --git a/roles/security/templates/rules.v6.j2 b/roles/security/templates/rules.v6.j2 new file mode 100644 index 0000000..14449cf --- /dev/null +++ b/roles/security/templates/rules.v6.j2 @@ -0,0 +1,43 @@ +*nat +:PREROUTING ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +{% if dns_enabled is defined and dns_enabled == "Y" %} +-A PREROUTING -s {{ vpn_network_ipv6 }} -p udp -m udp --dport 53 -j DNAT --to-destination fcaa::1:53 +{% endif %} +-A POSTROUTING -s {{ vpn_network_ipv6 }} -m policy --pol none --dir out -j MASQUERADE +COMMIT +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT DROP [0:0] +:ICMPV6-CHECK - [0:0] +:ICMPV6-CHECK-LOG - [0:0] +-A INPUT -i lo -j ACCEPT +-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A INPUT -p esp -j ACCEPT +-A INPUT -m ah -j ACCEPT +# rate limit ICMP traffic per source +-A INPUT -p icmpv6 --icmpv6-type echo-request -m hashlimit --hashlimit-upto 5/s --hashlimit-mode srcip --hashlimit-srcmask 32 --hashlimit-name icmp-echo-drop -j DROP +-A INPUT -p udp -m multiport --dports 500,4500 -j ACCEPT +-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT +# TODO: +# The IP of the resolver should be bound to a DUMMY interface. +# DUMMY interfaces are the proper way to install IPs without assigning them any +# particular virtual (tun,tap,...) or physical (ethernet) interface. +-A INPUT -d fcaa::1 -p udp --dport 53 -j ACCEPT +-A FORWARD -j ICMPV6-CHECK +-A FORWARD -p tcp --dport 445 -j DROP +-A FORWARD -p udp -m multiport --ports 137,138 -j DROP +-A FORWARD -p tcp -m multiport --ports 137,139 -j DROP +-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -m conntrack --ctstate NEW -s {{ vpn_network_ipv6 }} -m policy --pol ipsec --dir in -j ACCEPT +# this is so potential malicious traffic can not reach anywhere over the server +# https://www.insinuator.net/2016/05/cve-2016-1409-ipv6-ndp-dos-vulnerability-in-cisco-software/ +# other software implementations might be at least as broken as the one in CISCO gear. +-A ICMPV6-CHECK -p icmpv6 -m hl ! --hl-eq 255 --icmpv6-type router-solicitation -j ICMPV6-CHECK-LOG +-A ICMPV6-CHECK -p icmpv6 -m hl ! --hl-eq 255 --icmpv6-type router-advertisement -j ICMPV6-CHECK-LOG +-A ICMPV6-CHECK -p icmpv6 -m hl ! --hl-eq 255 --icmpv6-type neighbor-solicitation -j ICMPV6-CHECK-LOG +-A ICMPV6-CHECK -p icmpv6 -m hl ! --hl-eq 255 --icmpv6-type neighbor-advertisement -j ICMPV6-CHECK-LOG +-A ICMPV6-CHECK-LOG -j LOG --log-prefix "ICMPV6-CHECK-LOG DROP " +-A ICMPV6-CHECK-LOG -j DROP +COMMIT diff --git a/roles/vpn/handlers/main.yml b/roles/vpn/handlers/main.yml index 0885344..94ccdfc 100644 --- a/roles/vpn/handlers/main.yml +++ b/roles/vpn/handlers/main.yml @@ -4,9 +4,6 @@ - name: restart apparmor service: name=apparmor state=restarted -- name: save iptables - command: service netfilter-persistent save - - name: congrats debug: msg: diff --git a/roles/vpn/tasks/main.yml b/roles/vpn/tasks/main.yml index d9f64bf..b21f52b 100644 --- a/roles/vpn/tasks/main.yml +++ b/roles/vpn/tasks/main.yml @@ -20,16 +20,6 @@ - strongswan - netfilter-persistent -- name: Configure iptables so IPSec traffic can traverse the tunnel - iptables: table=nat chain=POSTROUTING source="{{ vpn_network }}" jump=MASQUERADE - notify: - - save iptables - -- name: Configure ip6tables so IPSec traffic can traverse the tunnel - iptables: ip_version=ipv6 table=nat chain=POSTROUTING source="{{ vpn_network_ipv6 }}" jump=MASQUERADE - notify: - - save iptables - - name: Setup the ipsec.conf file from our template template: src=ipsec.conf.j2 dest=/etc/ipsec.conf owner=root group=root mode=0644 notify: