如何在不中断现有连接的情况下启动 PF 服务?

如何在不中断现有连接的情况下启动 PF 服务?

我有一个启动 PF 防火墙的 Ansible 剧本。此时它会冻结,因为目标与 Ansible 正在执行的主机之间的 SSH 连接因此中断。有没有办法维持此连接,以便我可以继续执行下一个任务/剧本而无需重新运行?

答案1

你说得对。模块服务启动或重新加载时中断 Ansible ssh 连接普法. 请不要使用它

- service:
    name: pf
    state: started
    enabled: yes

相反,使用模块并让命令异步执行。设置pf_async_timeout以满足您的需求(大约 10 秒就够了。请参阅下面的日志)。例如,要启动普法

- name: start pf
  ansible.builtin.shell:
    cmd: >
      (( sleep 5; nohup service pf start 1>/dev/null 2>&1 ) & )
  async: "{{ pf_async_timeout }}"
  poll: 0

将其放入处理程序中。这样,它将作为 play 中的最后一个任务执行。由于异步执行,该任务不需要命令来完成。play 将立即完成。在远程主机上的日志中,您应该会看到类似于以下内容的内容

Apr  5 09:19:33 plane ansible-async_wrapper.py[20170]: Invoked with 743252776472 45 /home/asadmin/.ansible/tmp/ansible-tmp-1680679171.524129-1188854-111980374615608/AnsiballZ_command.py _
Apr  5 09:19:33 plane ansible-async_wrapper.py[20173]: Starting module and watcher
Apr  5 09:19:33 plane ansible-async_wrapper.py[20173]: Start watching 20174 (45)
Apr  5 09:19:33 plane ansible-async_wrapper.py[20174]: Start module (20174)
Apr  5 09:19:33 plane ansible-async_wrapper.py[20170]: Return async_wrapper task started.
Apr  5 09:19:35 plane ansible-async_wrapper.py[20174]: Module complete (20174)
Apr  5 09:19:38 plane ansible-async_wrapper.py[20173]: Done in kid B.

创建类似的处理程序来停止和重新加载普法。为了避免麻烦,最好先配置并验证配置,然后在验证配置后重新加载防火墙。查看我的角色freebsd_pf


剧本示例
shell> ansible-playbook freebsd-pf.yml
   ...
TASK [vbotka.freebsd_pf : pfconf: Configure rules using server2-pf.conf.j2 template] *************************************************
changed: [plane]
   ...
RUNNING HANDLER [vbotka.freebsd_pf : reload pf] **************************************************************************************
changed: [plane]

PLAY RECAP ***************************************************************************************************************************
plane: ok=20   changed=2    unreachable=0    failed=0    skipped=17   rescued=0    ignored=0

如果您想要继续执行相同的剧本或剧本,请等待连接。例如,

  ansible.builtin.wait_for:
    port: 22
    delay: 10

您还可以明确等待异步命令的完成。请参阅异步操作和轮询并寻找模块异步状态


问:它异步挂起我的连接......也就是说,在 Ansible 剧本中稍后(几秒钟后)。

答:对我来说是有效的。在剧本中,我等待端口 22 之后普法已重新加载,远程主机几次

shell> cat freebsd-pf.yml
- hosts: plane
  become: true
  roles:
    - vbotka.freebsd_pf
  post_tasks:
    - ansible.builtin.wait_for:
        port: 22
        delay: 10
    - ping:
    - pause: seconds=5
    - ping:
    - pause: seconds=5
    - ping:
    - pause: seconds=5
    - ping:

给出(节选)

shell> ansible-playbook freebsd-pf.yml
  ...
TASK [vbotka.freebsd_pf : pfconf: Configure rules using server2-pf.conf.j2 template] *************************************************
changed: [plane]

  ...

RUNNING HANDLER [vbotka.freebsd_pf : reload pf] **************************************************************************************
changed: [plane]

TASK [ansible.builtin.wait_for] ******************************************************************************************************
ok: [plane]

TASK [ping] **************************************************************************************************************************
ok: [plane]

TASK [pause] *************************************************************************************************************************
Pausing for 5 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [plane]

TASK [ping] **************************************************************************************************************************
ok: [plane]

TASK [pause] *************************************************************************************************************************
Pausing for 5 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [plane]

TASK [ping] **************************************************************************************************************************
ok: [plane]

TASK [pause] *************************************************************************************************************************
Pausing for 5 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [plane]

TASK [ping] **************************************************************************************************************************
ok: [plane]

PLAY RECAP ***************************************************************************************************************************
plane: ok=28   changed=2    unreachable=0    failed=0    skipped=17   rescued=0    ignored=0

配置示例

---

pf_install: false
pf_enable: true
pf_debug: false
pf_blacklistd_enable: true
pf_fail2ban_enable: true
pf_sshguard_enable: true
pf_backup_conf: true

pfconf_only: false
pfconf_validate: true
pfconf_validate_command: "pfctl -n -f %s"

pf_type: server2
srv2_pss_ssh: "# pass in quick on $ext_if proto tcp from any to any port ssh flags S/SA keep state"
srv2_sshabuse: |-
  table <sshabuse> persist
  block in quick from <sshabuse>
  pass in quick on $ext_if proto tcp from any to any port ssh flags S/SA keep state \
       (max-src-conn 10, max-src-conn-rate 3/5, overload <sshabuse> flush)

pf_log_all_blocked: true
pf_ext_if: wlan0
pf_ext_tcp_ports: "ssh, smtp, domain, www, pop3, auth, https, pop3s, 5500, 8080, 8081"
pf_ext_udp_ports: "domain, snmp, prospero, 5500"
pf_dhcp_ports: "bootps, bootpc"
pf_jails_ip: "10.1.0.0/24"

# nfs
pf_nfs_tcp_ports: "sunrpc, nfsd-status nfsd, lockd, 815, 956"
pf_nfs_udp_ports: "sunrpc, nfsd-keepalive, nfsd, lockd, 815, 956"
pf_nfs_clients: "10.1.0.0/24"
pf_rpc_ports: "1286, 1283, 1229"

pf_reserved_internal_net: "172.16.0.0/12, 192.168.0.0/16, 255.255.255.255/32"

pf_rules_custom:
  - dhcp_if="10.1.0.17"
  - ext_tcp_ports="{ {{ pf_ext_tcp_ports }} }"
  - ext_udp_ports="{ {{ pf_ext_udp_ports }} }"
  - dhcp_ports="{ {{ pf_dhcp_ports }} }"
  - jails_ip="{ {{ pf_jails_ip }} }"
  - nfs_clients="{ {{ pf_nfs_clients }} }"
  - nfs_tcp_ports="{ {{ pf_nfs_tcp_ports }} }"
  - nfs_udp_ports="{ {{ pf_nfs_udp_ports }} }"
  - rpc_ports="{ {{ pf_rpc_ports }} }"
  - syn_state="flags S/SA synproxy state"
  - sto_ext_ports="(max-src-conn-rate 500/10, overload <blocked_hosts> flush global)"
# DHCP
  - pass quick on $ext_if proto { tcp, udp } to $ext_if port $dhcp_ports
  - pass quick on $dhcp_if proto { tcp, udp } to $dhcp_if port $dhcp_ports
  # ext_tcp_ports
  - pass quick on $ext_if proto tcp to $ext_if port $ext_tcp_ports $syn_state $sto_ext_ports
  # ext_udp_ports
  - pass quick on $ext_if proto udp to $ext_if port $ext_udp_ports keep state $sto_ext_ports
  # nfs_clients nfs_ports
  - pass quick on $ext_if proto tcp from $nfs_clients to $ext_if port $nfs_tcp_ports keep state flags S/SA
  - pass quick on $ext_if proto udp from $nfs_clients to $ext_if port $nfs_udp_ports keep state
  - pass quick on $ext_if proto sctp from $nfs_clients to $ext_if keep state
  - pass quick on $ext_if proto { tcp, udp } from $nfs_clients to $ext_if port $rpc_ports keep state flags S/SA
  # jails_ip
  - pass in on $ext_if proto tcp to $jails_ip port $ext_tcp_ports $syn_state $sto_ext_ports
  - pass in on $ext_if proto udp to $jails_ip port $ext_udp_ports keep state $sto_ext_ports

pf_rules_nat:
  - nat on $ext_if inet from ! ($ext_if) to any -> ($ext_if)

# Howto: quick setup of jail on ZFS using ezjail with PF NAT/
# https://forums.freebsd.org/threads/howto-quick-setup-of-jail-on-zfs-using-ezjail-with-pf-nat.30063/
pf_rules_rdr:
  - rdr_jail_ports1="{ 80, 443 }"
  - rdr_jail_ports2="{ 80, 443 8080 8081 }"
  - rdr pass on $ext_if proto tcp from any to 10.1.0.61 port $rdr_jail_ports2 -> 127.0.2.11  # test_11
  - rdr pass on $ext_if proto tcp from any to 10.1.0.62 port $rdr_jail_ports1 -> 127.0.2.12  # test_12
  - rdr pass on $ext_if proto tcp from any to 10.1.0.63 port $rdr_jail_ports1 -> 127.0.2.13  # test_13
  - rdr pass on $ext_if proto tcp from any to 10.1.0.64 port $rdr_jail_ports1 -> 127.0.2.14  # test_14
  - rdr pass on $ext_if proto tcp from any to 10.1.0.65 port $rdr_jail_ports1 -> 127.0.2.15  # test_15
  - rdr pass on $ext_if proto tcp from any to 10.1.0.66 port $rdr_jail_ports1 -> 127.0.2.16  # test_16
  - rdr pass on $ext_if proto tcp from any to 10.1.0.67 port $rdr_jail_ports1 -> 127.0.2.17  # test_17
  - rdr pass on $ext_if proto tcp from any to 10.1.0.68 port $rdr_jail_ports1 -> 127.0.2.18  # test_18
  - rdr pass on $ext_if proto tcp from any to 10.1.0.69 port $rdr_jail_ports1 -> 127.0.2.19  # test_19
  - rdr pass on $ext_if proto tcp from any to 10.1.0.70 port $rdr_jail_ports1 -> 127.0.2.20  # test_20

# pf_ssh_whitelist:
# - 192.168.1.0/24
#
# NOTES: (1) nfs_ports: port 797 is needed for mountd;

# blacklistd
pf_blacklistd_flags: "-r"
pf_blacklistd_conf_remote: []
pf_blacklistd_conf_local:
  - {adr: ssh, type: stream, proto: "*", owner: "*", name: "*", nfail: "3", disable: 24h}
  - {adr: ftp, type: stream, proto: "*", owner: "*", name: "*", nfail: "3", disable: 24h}
  - {adr: smtp, type: stream, proto: "*", owner: "*", name: "*", nfail: "3", disable: 24h}
  - {adr: smtps, type: stream, proto: "*", owner: "*", name: "*", nfail: "3", disable: 24h}
  - {adr: submission, type: stream, proto: "*", owner: "*", name: "*", nfail: "3", disable: 24h}
  - {adr: "*", type: "*", proto: "*", owner: "*", name: "*", nfail: "3", disable: "60"}
pf_blacklistd_rcconf:
  - {regexp: blacklistd_flags, line: "{{ pf_blacklistd_flags }}"}

# EOF
...

相关内容