分类: 网络和通信

  • 为nginx配置coraza WAF

    ./configure --user=httpd --group=httpd --with-http_ssl_module --add-dynamic-module=/path/to/coraza-nginx --with-compat
    
        coraza on;
        coraza_transaction_id "webserver-$request_id";
        coraza_rules_file /etc/coraza/main.conf;
    

    其中main.conf为配置的WAF规则例如

    Include /etc/coraza/rules/REQUEST-913-SCANNER-DETECTION.conf
    Include /etc/coraza/rules/REQUEST-922-MULTIPART-ATTACK.conf
    • 重新启动nginx加载WAF,查看nginx的error.log确定WAF规则加载完成

  • wordpress本站搭建过程

    • 准备工作
    1. 购买云主机
    2. 购买对应的域名并完成备案注册
    • 本站使用宝塔Linux发行版,除nginx之外使用宝塔Linux dnf 安装软件
    配置编译参数选项
    declare -x CC="gcc"
    declare -x CFLAGS="-O2 -Wall -fstack-protector-all -mindirect-branch=thunk -mfunction-return=thunk"
    
    使用 
    ./configure --user=httpd --group=httpd --with-http_ssl_module
    配置nginx
    
    使用
    make install 安装nginx到目标文件夹
    • 为nginx服务添加基于nft的rate控制,下面的例子为一个基础防火墙配置
    /etc/nft_protection.nft
    
    table inet filter {
    	set synflood {
    		type ipv4_addr
    		size 65535
    		flags dynamic
    	}
    
    	set limitrate {
    		type ipv4_addr
    		size 65535
    		flags dynamic
    	}
    
    	chain input {
    		type filter hook input priority filter; policy accept;
    		tcp dport 80 ct state new update @synflood { ip saddr limit rate over 20/second burst 5 packets } counter reject with tcp reset
    		tcp dport 80 ct state new update @limitrate { ip saddr ct count over 100 } counter reject with tcp reset
                    tcp dport 443 ct state new update @synflood { ip saddr limit rate over 20/second burst 5 packets } counter reject with tcp reset
                    tcp dport 443 ct state new update @limitrate { ip saddr ct count over 100 } counter reject with tcp reset
    	}
    }
    
    • 修改默认的 nginx systemd service并配置letsencrypt的参数,删除nginx运行时使用root账号运行,由于nginx直接提供对外的https/https访问,所以在systemd.service中根据使用需要配置沙箱
    /usr/lib/systemd/system/nginx.service
    
    [Unit]
    Description=The NGINX HTTP and reverse proxy server
    After=network.target remote-fs.target nss-lookup.target
    
    [Service]
    Environment="LD_PRELOAD=/usr/lib64/libclang_rt.scudo_standalone.so"#根据需要配置,本站使用LLVM的libscudo替换glibc的内存分配器
    Type=forking
    ExecStartPre=+/usr/sbin/nft flush table inet filter           # nft 需要root权限配置netfilter
    ExecStartPre=+/usr/sbin/nft -f /etc/nft_protection.nft        # nft 需要root权限配置netfilter
    ExecStartPre=/usr/local/bin/nginx -t -e /var/log/nginx/logs/error.log -c /usr/local/nginx/conf/nginx.conf
    ExecStart=/usr/local/bin/nginx -e /var/log/nginx/logs/error.log -c /usr/local/nginx/conf/nginx.conf
    ExecReload=/usr/local/bin/nginx -s reload -e /var/log/nginx/logs/error.log -c /usr/local/nginx/conf/nginx.conf
    ExecStartPost=/bin/chmod 664 /usr/local/nginx/logs/nginx.pid
    PrivateTmp=true
    User=httpd
    Group=httpd
    AmbientCapabilities=CAP_NET_BIND_SERVICE
    ProtectSystem=full
    ProtectHome=true
    ProtectKernelTunables=true
    ProtectKernelModules=true
    LockPersonality=true
    SystemCallFilter=~@chown @module @clock @privileged @keyring @reboot @swap @sync @debug @pkey @cpu-emulation @aio @mount
    SystemCallErrorNumber=EPERM 
    InaccessiblePaths=/root /home /boot
    BindPaths=/usr/local/nginx/etc:/etc
    ReadOnlyPaths=/etc/letsencrypt
    ReadWritePaths=/var/log/nginx/logs /usr/local/nginx/logs/ /usr/local/nginx/client_body_temp/ /usr/local/nginx/fastcgi_temp/ /usr/local/nginx/scgi_temp/ /usr/local/nginx/uwsgi_temp/ /usr/local/nginx/proxy_temp/
    SystemCallArchitectures=native
    NoNewPrivileges=true
    MemoryDenyWriteExecute=true
    PrivateDevices=true
    
    [Install]
    WantedBy=multi-user.target
    
    • 配置nginx的配置文件/usr/local/nginx/etc/conf/nginx.conf, certbot会更新此配置文件添加对应的证书信息
    /usr/local/nginx/etc/conf/nginx.conf
    
    worker_processes  1;
    
    error_log  /var/log/nginx/logs/error.log;
    error_log  /var/log/nginx/logs/error.log  notice;
    error_log  /var/log/nginx/logs/error.log  info;
    
    
    events {
        worker_connections  1024;
    }
    
    http {
        include       mime.types;
        include       fastcgi.conf;
        default_type  application/octet-stream;
    
        error_log   /var/log/nginx/logs/error.log;
        server_tokens off;
        sendfile        on;
        fastcgi_buffering off;
    
        keepalive_timeout  65;
    
        upstream php {
            server unix:/var/run/php-fpm/www.sock;
        }
    
        server {
            server_name  对应的域名;
    
    	client_max_body_size 5m;
    
    	root /var/lib/www/html;
            index index.php;
    
            location / {
                try_files $uri $uri/ /index.php?$args;
    	}
    
            location ~ \.php$ {
                try_files $uri =404;
                include fastcgi.conf;
                fastcgi_pass php;
            }
    
    	location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    	    expires 1d;
    	    log_not_found on;
    	    try_files $uri $uri/ /index.php?$args; 
    	}
    
            location ~* \.webm$ {
                gzip off;
                limit_rate 5m;
    	    tcp_nopush on;
    	    tcp_nodelay on;
    	    sendfile on;
    	    max_ranges 5;
            }
    
    	# Deny access to hidden files (like .htaccess or .git)
    	location ~ /\. {
    	    deny all;
    	    access_log off;
    	    log_not_found off;
    	}
    
    	# Security: Deny direct execution of PHP files in the uploads folder
    	location ~* /(?:uploads|files)/.*\.php$ {
    	    deny all;
    	}
    
            # redirect server error pages to the static page /50x.html
            #
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
    
            listen 443 ssl;
    
        }
    
    }
    
    • 使用发行版安装php-fpm, mariadb和certbots
    • 配置php-fpm服务和nginx配套工作
    /usr/lib/systemd/system/php-fpm.service
    
    [Unit]
    Description=The PHP FastCGI Process Manager
    After=syslog.target network.target
    
    [Service]
    Type=notify
    ExecStart=/usr/sbin/php-fpm --nodaemonize
    ExecReload=/bin/kill -USR2 $MAINPID
    PrivateTmp=true
    RuntimeDirectory=php-fpm
    RuntimeDirectoryMode=0755
    ProtectSystem=full
    ProtectHome=true
    ProtectKernelTunables=true
    ProtectKernelModules=true
    LockPersonality=true
    SystemCallFilter=~@chown @module @clock @privileged @keyring @reboot @swap @sync @debug @pkey @cpu-emulation @aio @mount
    SystemCallErrorNumber=EPERM 
    ReadWritePaths=/var/log/php-fpm
    InaccessiblePaths=/root /home /boot
    BindPaths=/var/lib/php/etc:/etc
    SystemCallArchitectures=native
    NoNewPrivileges=true
    MemoryDenyWriteExecute=true
    PrivateDevices=true
    User=httpd
    Group=httpd
    RestrictAddressFamilies=AF_UNIX AF_INET
    TasksMax=256
    AmbientCapabilities=CAP_NET_ADMIN
    CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
    
    
    [Install]
    WantedBy=multi-user.target
    
    
    
    /var/lib/php/etc/php.ini
    
    expose_php = Off
    • 配置mariadb只使用unix socket通信
    /usr/lib/systemd/system/mariadb.service
    
    [Unit]
    Description=MariaDB 10.11 database server
    Documentation=man:mariadbd(8)
    Documentation=https://mariadb.com/kb/en/library/systemd/
    After=network.target
    
    [Install]
    WantedBy=multi-user.target
    Alias=mysql.service
    Alias=mysqld.service
    
    [Service]
    Environment="LD_PRELOAD=/usr/lib64/libclang_rt.scudo_standalone.so"
    Type=notify
    User=mysql
    Group=mysql
    
    ExecStartPre=/usr/libexec/mariadb-check-socket
    # '%n' expands to 'Full unit name'; man systemd.unit
    ExecStartPre=/usr/libexec/mariadb-prepare-db-dir %n
    # MYSQLD_OPTS here is for users to set in /etc/systemd/system/mariadb@.service.d/MY_SPECIAL.conf
    # Note: we set --basedir to prevent probes that might trigger SELinux alarms,
    # per bug #547485
    ExecStart=/usr/libexec/mariadbd --basedir=/usr $MYSQLD_OPTS $_WSREP_NEW_CLUSTER
    ExecStartPost=/usr/libexec/mariadb-check-upgrade
    
    # Setting this to true can break replication and the Type=notify settings
    # See also bind-address MariaDB option.
    PrivateNetwork=false
    ProtectSystem=full
    ProtectHome=true
    ProtectKernelModules=true
    LockPersonality=true
    ReadWritePaths=/var/lib/mysql /var/log/mariadb /run/mariadb
    SystemCallArchitectures=native
    NoNewPrivileges=true
    MemoryDenyWriteExecute=true
    PrivateDevices=true
    RestrictAddressFamilies=AF_UNIX
    
    KillSignal=SIGTERM
    
    # Don't want to see an automated SIGKILL ever
    SendSIGKILL=no
    
    # Restart crashed server only, on-failure would also restart, for example, when
    # my.cnf contains unknown option
    Restart=on-abort
    RestartSec=5s
    
    UMask=007
    
    # Give a reasonable amount of time for the server to start up/shut down
    TimeoutSec=300
    
    # Place temp files in a secure directory, not /tmp
    PrivateTmp=true
    
    
    配置mariadb服务端配置
    /etc/my.cnf.d/mariadb-server.cnf
    
    [mysqld]
    datadir=/var/lib/mysql
    socket=/var/lib/mysql/mysql.sock
    log-error=/var/log/mariadb/mariadb.log
    pid-file=/run/mariadb/mariadb.pid
    
    [galera]
    skip-networking
    

    • 安装完成certbot之后配置自动更新/usr/lib/systemd/system/certbot-renew.service
    [Unit]
    Description=This service automatically renews any certbot certificates found
    
    [Service]
    EnvironmentFile=/etc/sysconfig/certbot
    Type=oneshot
    ExecStart=+/usr/bin/certbot renew --noninteractive --no-random-sleep-on-renew $PRE_HOOK $POST_HOOK $RENEW_HOOK $DEPLOY_HOOK $CERTBOT_ARGS      # certbot需要root权限,使用systemctl操作nginx,本站未自定义hook,使用root运行certbot
    User=certbot                            
    Group=httpd                             
    PrivateTmp=true
    ProtectSystem=full
    ProtectHome=true
    AmbientCapabilities=CAP_NET_BIND_SERVICE
    ProtectKernelTunables=true
    ProtectKernelModules=true
    LockPersonality=true
    SystemCallFilter=~@chown @module @clock @privileged @keyring @reboot @swap @sync @debug @pkey @cpu-emulation @aio @mount
    SystemCallErrorNumber=EPERM 
    BindPaths=/usr/local/nginx/etc:/etc
    ReadWritePaths=/var/lib/letsencrypt /var/log/letsencrypt /etc/letsencrypt /usr/local/nginx/logs/ /var/log/nginx/ /usr/local/nginx/conf/
    InaccessiblePaths=/root /home /boot /dev 
    SystemCallArchitectures=native
    NoNewPrivileges=true
    MemoryDenyWriteExecute=true
    PrivateDevices=true
    
    • 修改运行时需要的文件从/etc/复制到/usr/local/nginx/etc/
    sudo cp /etc/group /usr/local/nginx/etc/
    sudo cp /etc/passwd /usr/local/nginx/etc/
    
    删除/usr/local/nginx/etc/group和/usr/local/nginx/etc/passwd文件内的账号只保留httpd和必要的账号
    
    复制所有nginx相关的配置到 /usr/local/nginx/etc/
    
    sudo cp -rf /etc/crypto-policies /usr/local/nginx/etc/
    sudo cp -rf /etc/letsencrypt /usr/local/nginx/etc/
    sudo cp -rf /etc/nginx /usr/local/nginx/etc/
    sudo cp -rf /etc/pki /usr/local/nginx/etc/
    sudo cp -rf /etc/ssl /usr/local/nginx/etc/
    
    • 修改运行时需要的文件从/etc/复制到/var/lib/php/etc/
    sudo cp /etc/passwd /var/lib/php/etc/
    
    删除 /var/lib/php/etc/passwd 内的账号 只保留需要的httpd
    
    复制所有php相关配置到 /var/lib/php/etc/
    
    sudo cp -rf /etc/php.d /var/lib/php/etc/
    sudo cp /etc/php.ini /var/lib/php/etc/
    sudo cp -rf /etc/wordpress /var/lib/php/etc/
    sudo cp -rf /etc/php-fpm.d /var/lib/php/etc/
    
    
    • 使用systemctl 重启nginx, php-fpm
    • 使用systemctl 测试 certbot-renew