Lab 023

Ansible Playbook自动配置SSH

---
- name: 16_PRO_SSHConfig.yml
  hosts: all
  gather_facts: yes
  vars:
    allow_root: True
    allow_password: False
    ssh_port: 34522
    ssh_change_port: True

  tasks:
    - name: Delete GSS
      lineinfile: dest=/etc/ssh/sshd_config state=absent regexp=".*GSS.*"
  
    - name: Set UseDNS no
      lineinfile: dest=/etc/ssh/sshd_config regexp=".*UseDNS.*" line="UseDNS no"

    - name: if permit root login via publickey
      lineinfile: dest=/etc/ssh/sshd_config regexp="^PermitRootLogin " insertafter="^#PermitRootLogin " line="PermitRootLogin without-password" 
      when: allow_root == 'True'

    - name: if not allow rootlogin
      lineinfile: dest=/etc/ssh/sshd_config regexp="^PermitRootLogin " insertafter="^#PermitRootLogin " line="PermitRootLogin no"
      when: allow_root == 'False'

    - lineinfile: dest=/etc/ssh/sshd_config regexp="^PasswordAuthentication" line="PasswordAuthentication yes"
      when: allow_password == 'True'

    - lineinfile: dest=/etc/ssh/sshd_config regexp="^PasswordAuthentication " line="PasswordAuthentication no"
      when: allow_password == 'False'

    - lineinfile: dest=/etc/ssh/sshd_config regexp="^RSAAuthentication " line="RSAAuthentication yes"
      when: allow_password == 'False'

    - lineinfile: dest=/etc/ssh/sshd_config regexp="^PubkeyAuthentication " line="PubkeyAuthentication yes"
      when: allow_password == 'False'

    - lineinfile: dest=/etc/ssh/sshd_config regexp="^AuthorizedKeysFile " line="AuthorizedKeysFile .ssh/authorized_keys"
      when: allow_password == 'False'

    - lineinfile: dest=/etc/ssh/sshd_config regexp=".*Port.*" line="Port {{ssh_port}}"
      when: ssh_change_port == 'True'

    - name: restart sshd service
      service: name=sshd state=restarted

Ansible Playbook安装基础组件

---
# ansible-playbook -l app1 base_component.yml
- name: install base componnet [0.0.1]
  hosts: all
  gather_facts: yes
  vars:
    update_all: True

  tasks:
  - name: update system
    shell: yum makecache ; yum update -y
    when: (ansible_os_family == "RedHat" and update_all == 'True')

  - name: install base component For RedHat Family
    package: name={{ item }} update_cache=no state=latest
    with_items:
     - net-tools
     - automake
     - autoconf
     - dstat
     - gcc
     - gcc-c++
     - gdb
     - make
     - nc
     - telnet
     - vim
     - tree
     - ntpdate
     - libselinux-python
     - chkconfig
     - sysstat
     - iptraf
     - openssl
     - openssl-devel
     - fail2ban
     - smem
    when: ansible_os_family == "RedHat"

  - service: name=fail2ban state=restarted

Ansible Playbook内核参数调优

---
- name: Linux kernel tuning [0.0.2]
  hosts: all
  gather_facts: no
  vars:

  tasks:
    - sysctl: name={{ item.key }} value={{ item.value }} state=present
      with_items:
        - { key: "vm.swappiness", value: "5" }
        - { key: "net.ipv4.tcp_syncookies", value: "1" }
        - { key: "net.ipv4.conf.all.log_martians", value: "0" }
        - { key: "net.core.somaxconn", value: "65535" }
        - { key: "net.ipv4.tcp_max_syn_backlog", value: "30000" }
        - { key: "net.core.netdev_max_backlog", value: "32768" }
        - { key: "fs.file-max", value: "1000000" }
        - { key: "net.ipv4.ip_local_port_range", value: "10000 65535" }
        - { key: "net.ipv4.udp_rmem_min", value: "8192" }
        - { key: "net.ipv4.udp_wmem_min", value: "8192" }
        - { key: "net.ipv4.conf.all.send_redirects", value: "1" } 
        - { key: "net.ipv4.conf.all.accept_redirects", value: "1" }
        - { key: "net.ipv4.conf.all.accept_source_route", value: "1"}
        - { key: "net.ipv4.ip_forward", value: "0" }
        - { key: "net.ipv4.tcp_slow_start_after_idle", value: "0" }
        - { key: "net.ipv4.tcp_keepalive_time", value: "60" }
        - { key: "net.ipv4.tcp_max_tw_buckets", value: "2000000" }
        - { key: "net.ipv4.tcp_fin_timeout", value: "10" }
        - { key: "net.ipv4.tcp_tw_reuse", value: "1" }
        - { key: "net.ipv4.tcp_tw_recycle", value: "1" }
        - { key: "net.ipv4.tcp_keepalive_intvl", value: "15" }
        - { key: "net.ipv4.tcp_keepalive_probes", value: "5" }
        - { key: "net.ipv4.tcp_max_orphans", value: "3276800" }
        - { key: "net.ipv4.tcp_mem", value: "94500000 915000000927000000" }
        - { key: "net.ipv4.tcp_syn_retries", value: "2" }
        - { key: "net.ipv4.tcp_synack_retries", value: "2" }
        - { key: "net.ipv4.tcp_timestamps", value: "0" }
        - { key: "net.core.wmem_max", value: "16777216" }
        - { key: "net.core.rmem_max", value: "16777216" }
        - { key: "net.core.rmem_default", value: "8388608" }
        - { key: "net.core.wmem_default", value: "8388608" }

Ansible Playbook创建app用户

---
# ansible-playbook -l app1 02_PRO_UlimitApp.yml
# It works with new version openssh. openssh-5.3 has lots of bugs.
- name: create user and ulimit [0.0.2]
  hosts: all
  gather_facts: no
  vars:
    uuser: nginx

  tasks:
    - name: create user
      shell: useradd {{ uuser }}
      ignore_errors: true

    - name: passwd lock user
      shell: passwd -l {{ uuser }}
      ignore_errors: true

    - name: modify /etc/security/limit.conf
      pam_limits: domain={{ item.domain }} limit_type={{ item.type }} limit_item={{ item.item }} value={{ item.value }}
      ignore_errors: True
      with_items:
        - { domain: '{{uuser}}', type: 'soft', item: 'nofile', value: '63536' }
        - { domain: '{{uuser}}', type: 'hard', item: 'nofile', value: '63536' }
        - { domain: '{{uuser}}', type: 'soft', item: 'nproc', value: '63536' }
        - { domain: '{{uuser}}', type: 'hard', item: 'nproc', value: '63536' }

    - name: show process
      shell: ulimit -a
      become_user: "{{ uuser }}"
      with_items:
        - "{{ uuser }}"
      ignore_errors: True
      register: ulimitOut

    - debug: msg="ulimit -a ~> {{ ulimitOut }}"

Nginx自动编译脚本

自动编译Nginx+OpenSSL

请按需更改版本号

内详

Windows 10命令行TCP端口转发

添加端口转发:通过本机 192.168.1.88:60544访问远程地址192.168.1.103:6544

netsh interface portproxy add v4tov4 listenaddress=192.168.1.88 listenport=60544 connectaddress=192.168.1.103 connectport=6544

 

删除端口转发

netsh interface portproxy delete v4tov4 listenaddress=192.168.1.88 listenport=60544

「长期更新」OpenSSH Client Config Tips

 ~/.ssh/config 配置文件详解

# 全局配置
Host *
  # 启用会话重用("持久化连接")功能
  # 会话重用意味着其他人也能登录你正在连接的服务器, 除非用户隔离
  ControlMaster auto
  # 会话存放路径 注意存放路径, 不推荐存放到/tmp目录
  # 如果链路端开, 会话已经无效, 需要kill掉ssh进程或删掉会话文件
  ControlPath ~/.ssh/sockets/%r@%h-%p
  # 会话有效时间 单位分钟
  ControlPersist 600
  # 允许转发秘钥到远端服务器, 再次跳转其他服务器不用秘钥
  ForwardAgent yes
  # 转发X11协议
  ForwardX11 no
  # 转发X11协议到信任服务器
  ForwardX11Trusted yes
  # SSH 2.0协议
  Protocol 2
  # 发送心跳包间隔 单位秒
  ServerAliveInterval 60
  # 服务器断开心跳数量
  # 也就是"持久化连接"会在网络断开30*60秒之后自动断开
  ServerAliveCountMax 30

# 远端服务器缩写 直接ssh host1连接
Host host1
  # 使用加密算法 需要配合远端sshd_config
  Ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com
  # 服务器IP或域名
  HostName x.x.x.x
  # 允许转发秘钥到远端服务器, 二次跳转免登陆. 远端使用ssh-add -L查看
  ForwardAgent yes
  # 登录的用户名
  User root
  # 服务器SSH端口
  port 56722
  # 使用跳板机登录 跳板机配置秘钥免登陆
  ProxyJump 192.168.1.100
  # 使用跳板机NC登录,比ProxyJump麻烦些
  ProxyCommand ssh 192.168.1.100 nc %h %p
  # 映射本地80端口到远端60080端口
  RemoteForward 127.0.0.1:60080 127.0.0.1:80
  # 映射远端443端口到本地10443端口
  LocalForward 127.0.0.1:10443 127.0.0.1:443
  # 认证秘钥
  IdentityFile /path/to/your/identify

Qualys SSL Labs满分Nginx配置

  1. 满分并不表示安全
  2. 加密算法不能低于256位(所以TLS 1.3不一定能满分)
  3. 配置无删减, 仅隐藏域名

内详

给VPS添加SWAP分区

以root账户执行以下命令

# 创建一个2GB大小的SWAP文件
dd if=/dev/zero of=/swapfile bs=1k count=2097152
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
swapon -s
echo "/swapfile none swap sw 0 0" >> /etc/fstab

# 挂载SWAP分区
swapon -a

# 卸载SWAP分区
swapoff -a

# 查看SWAP分区使用情况
free -m

Ansible Playbook申请Let's Encrypt证书

---
- name: Let's Encrypt CA CentOS 7.3[0.0.1] @LastModify 2018-11-13
  hosts: all
  gather_facts: yes
  vars:
    domain: www.***.com
    mail: ****@qq.com

  tasks:
  - yum: name=yum-utils state=latest
  - shell: yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional
  - yum: name=python2-certbot-nginx state=latest
  - cron:
      name: "let's encrypt cron"
      minute: "0"
      hour: "0,12"
      job: "python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew --rsa-key-size 4096"
  - name: certbot --rsa-key-size 4096 --nginx -d {{ domain }} --agree-tos --email {{ mail }} --no-bootstrap --server https://acme-v02.api.letsencrypt.org/directory
    shell: certbot --rsa-key-size 4096 --nginx -d {{ domain }} --agree-tos --email {{ mail }} --no-bootstrap --server https://acme-v02.api.letsencrypt.org/directory
    ignore_errors: yes
  - name: test renew
    shell: certbot renew --dry-run
    ignore_errors: yes
  # - shell: openssl dhparam -out /etc/letsencrypt/live/{{domain}}/dhparams.pem 4096