此次nginx升级主要是为了解决 nginx 安全漏洞(CVE-2021-23017),因为是yum安装的,没找到补丁文件所以采用升级的方式,
一、系统与应用环境
nginx版本(YUM安装的): [root@localhost ~]# yum -y install nginx-1.16.1-1.el7.ngx [root@localhost ~]# nginx -V nginx version: nginx/1.16.1 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) built with OpenSSL 1.0.2k-fips 26 Jan 2017 TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' GCC版本: [root@localhost ~]# gcc -v 使用内建 specs。 COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper 目标:x86_64-redhat-linux 配置为:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux 线程模型:posix gcc 版本 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
此次平滑升级是为了在不影响服务的情况下升级,可以写一个动态页面去测试是否断开 [root@localhost ~]# cd /etc/nginx/conf.d/ [root@localhost conf.d]# vim default.conf (修改,去掉注释,修改页面路径、端口) 30 location ~ \.php$ { 31 root /var/www; 32 fastcgi_pass 127.0.0.1:80; 33 fastcgi_index index.php; 34 fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 35 include fastcgi_params; 36 } 37 #保存退出 [root@localhost www]# cat test.php #编写一个动态页面 <?php echo "今天是:" . date("h:i:sa") . "\n"; ?> 安装php [root@localhost www]# yum -y install epel-release [root@localhost www]# rpm -Uvh http://rpms.remirepo.net/enterprise/remi-release-7.rpm [root@localhost www]# 1 [root@localhost www]# yum -y install yum-utils [root@localhost www]# yum-config-manager --enable remi-php72 [root@localhost www]# yum -y install php php-opcache [root@localhost www]# yum -y install php-mysql php-gd php-ldap php-odbc php-pear php-xml php-xmlrpc php-mbstring php-soap curl curl-devel [root@localhost www]# yum -y install php72-php-fpm.x86_64 [root@localhost www]# systemctl restart php72-php-fpm [root@localhost www]# netstat -tunlp|grep 9000 [root@localhost www]# vim /etc/opt/remi/php72/php-fpm.d/www.conf 。。。。。。修改user和group为nginx 23 ; RPM: apache user chosen to provide access to the same directories as httpd 24 user = nginx 25 ; RPM: Keep a group allowed to write in log dir. 26 group = nginx 27 。。。。。。 #保存退出 [root@localhost www]# nginx -s reload 再开一个终端,进行测试 [root@localhost ~]# cat aaa.sh #!/bin/bash while [ ture ] do sleep 2 curl http://10.0.2.111/test.php if [ $? -ne 0 ];then echo "exit" exit 0 fi done [root@localhost ~]# bash aaa.sh #执行脚本即可,观察中间升级时是否会中断 今天是:08:54:56am 今天是:08:54:58am 今天是:08:55:00am
二、实验步骤
(1)查看现有nginx配置
[root@localhost ~]# nginx -V #configure arguments:就是配置信息,待会需要使用,全部都是!!!不要复制少了 nginx version: nginx/1.16.1 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) built with OpenSSL 1.0.2k-fips 26 Jan 2017 TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
(2)安装依赖包(安装之前可以使用脚本扫一下)
[root@VM-0-14-centos ~]# yum -y install GeoIP GeoIP-devel GeoIP-data perl-devel perl-ExtUtils-Embed gd-devel libxml2 libxslt-devel gperftools pcre-devel openssl openssl-devel ———————————————————————————————————————— [root@VM-0-14-centos ~]# cat aaa GeoIP GeoIP-devel GeoIP-data perl-devel perl-ExtUtils-Embed gd-devel libxml2 libxslt-devel gperftools pcre-devel openssl openssl-devel [root@VM-0-14-centos ~]# for i in `cat aaa`;do rpm -qa $i ;done #扫到没有的再去安装 GeoIP-1.5.0-14.el7.x86_64 libxml2-2.9.1-6.el7.5.x86_64 libxslt-devel-1.1.28-6.el7.x86_64 pcre-devel-8.32-17.el7.x86_64 openssl-1.0.2k-22.el7_9.x86_64 openssl-devel-1.0.2k-22.el7_9.x86_64 [root@VM-0-14-centos ~]# yum -y install GeoIP-devel GeoIP-data perl-devel perl-ExtUtils-Embed gd-devel gperftools ————————————————————————————————————————
(3)安装新版本的nginx-1.20.1
[root@localhost ~]# wget http://nginx.org/download/nginx-1.20.1.tar.gz [root@localhost ~]# tar -xf nginx-1.20.1.tar.gz [root@localhost ~]# cd nginx-1.20.1/ [root@localhost nginx-1.20.1]# ll 总用量 788 drwxr-xr-x 6 1001 1001 326 11月 24 16:46 auto -rw-r--r-- 1 1001 1001 311503 5月 25 2021 CHANGES -rw-r--r-- 1 1001 1001 475396 5月 25 2021 CHANGES.ru drwxr-xr-x 2 1001 1001 168 11月 24 16:46 conf -rwxr-xr-x 1 1001 1001 2590 5月 25 2021 configure drwxr-xr-x 4 1001 1001 72 11月 24 16:46 contrib drwxr-xr-x 2 1001 1001 40 11月 24 16:46 html -rw-r--r-- 1 1001 1001 1397 5月 25 2021 LICENSE drwxr-xr-x 2 1001 1001 21 11月 24 16:46 man -rw-r--r-- 1 1001 1001 49 5月 25 2021 README drwxr-xr-x 9 1001 1001 91 11月 24 16:46 src [root@localhost nginx-1.20.1]# cd /etc/nginx/ #去旧版本的nginx备份一下文件 [root@localhost nginx]# ls conf.d default.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf nginx.conf.bak scgi_params uwsgi_params win-utf [root@localhost nginx]# cp nginx.conf nginx.conf.bak [root@localhost ~]# cd nginx-1.20.1/ [root@localhost nginx-1.20.1]# cp auto/lib/openssl/conf{,.bak} [root@localhost nginx-1.20.1]# vim auto/lib/openssl/conf (这个有时候已经去掉了) 修改:39,42s@/.openssl@@g修改去掉.openssl/ # CORE_INCS="$CORE_INCS $OPENSSL/.openssl/include" # CORE_DEPS="$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h" # CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a" # CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a" # CORE_LIBS="$CORE_LIBS $NGX_LIBDL" 改为: CORE_INCS="$CORE_INCS $OPENSSL/include" CORE_DEPS="$CORE_DEPS $OPENSSL/include/openssl/ssl.h" CORE_LIBS="$CORE_LIBS $OPENSSL/lib/libssl.a" CORE_LIBS="$CORE_LIBS $OPENSSL/lib/libcrypto.a" CORE_LIBS="$CORE_LIBS $NGX_LIBDL" #保存退出 进行配置,使用旧版本nginx的配置,就是一开始使用-V查看的配置即可 [root@localhost nginx-1.20.1]# ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' --with-compat 实例:这里需要把原本nginx的模块也编译进去,到时候升级时需要进行选择 ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' --with-compat --with-openssl=/home/openssl-1.1.1l --with-http_stub_status_module --with-http_ssl_module --with-stream=dynamic --with-mail=dynamic --with-http_image_filter_module=dynamic --with-http_xslt_module=dynamic --with-http_perl_module=dynamic —————————————————————————————————————————————— 报错解决: (1)openssl找不到,这里找不到是因为需求还对openssl进行了升级,也是为了解决漏洞 ./configure: error: SSL modules require the OpenSSL library. You can either do not enable the modules, or install the OpenSSL library into the system, or build the OpenSSL library statically from the source with nginx by using --with-openssl=<path> option. 这个报错是找不到openssl的位置,即便已经有了,如果没有的话使用 yum -y install openssl openssl-devel安装即可 没有的话需要在末尾添加--with-openssl=/home/openssl-1.1.1l ______________________________________________ [root@localhost nginx-1.20.1]# echo $? 0 [root@localhost nginx-1.20.1]# make #编译,不需要make install安装!!!!!!否则会覆盖旧nginx的目录 。。。。。。等待编译完成 [root@localhost nginx-1.20.1]# echo $? 0
(4)平滑升级
网上很多yum平滑升级时,在检查配置文件的时候会报错,这个时候大多数文章写的都是把指定模块的路径给注释掉,但是显然是不可能的,在实际生产环境中,有的模块是正在使用的,所以我这里在编译新版本的时候把旧版本nginx的模块也全部编译了,在配置文件中直接重新指定,就不会报错,但是最后在发送平滑迁移信号后无法生产oldbin文件,最终导致nginx平滑升级失败
(1)备份旧nginx的二进制文件替换成新nginx的二进制文件,中间nginx是不会停止的 [root@localhost nginx-1.20.1]# mv /usr/sbin/nginx /usr/sbin/nginx_$(date +%F) [root@localhost nginx-1.20.1]# cp objs/nginx /usr/sbin/ (2)检测nginx语法是否正确 [root@localhost nginx-1.20.1]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful #需要先修改配置文件,把模块的位置都指向新编译好的模块路径,否则会报错 10 # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. 11 #include /usr/share/nginx/modules/*.conf; 12 13 load_module /root/nginx-1.20.1/objs/ngx_http_image_filter_module.so; 14 #load_module /root/nginx-1.20.1/objs/ngx_http_perl_module.so; 15 load_module /root/nginx-1.20.1/objs/ngx_http_xslt_filter_module.so; 16 load_module /root/nginx-1.20.1/objs/ngx_mail_module.so; 17 load_module /root/nginx-1.20.1/objs/ngx_stream_module.so; 18 #####下面是正常的步骤是我在测试环境,没有模块时做的,在生产环境中到这步就出错了,无法生产oldbin文件 (3)给nginx发送平滑迁移的信号,需要获取pid [root@localhost nginx-1.20.1]# kill -USR2 `cat /run/nginx.pid` (4)查看nginx.pid,会多出一个nginx.pid.oldbin [root@localhost nginx-1.20.1]# ll /run/nginx* -rw-r--r-- 1 root root 5 11月 24 17:04 /run/nginx.pid -rw-r--r-- 1 root root 6 11月 24 16:47 /run/nginx.pid.oldbin #####下面是正常的步骤,但是到上一步,就出错了,无法生产oldbin文件 (5)从容关闭旧的nginx进程 [root@localhost nginx-1.20.1]# kill -WINCH `cat /run/nginx.pid.oldbin` (6)这个时候不重载配置,启动旧的工作进程 [root@localhost nginx-1.20.1]# kill -HUP `cat /run/nginx.pid.oldbin` (7)结束工作进程 [root@localhost nginx-1.20.1]# kill -QUIT `cat /run/nginx.pid.oldbin` (8)升级成功 [root@localhost nginx-1.20.1]# nginx -V nginx version: nginx/1.20.1 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) built with OpenSSL 1.0.2k-fips 26 Jan 2017 TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' (9)查看nginx语法,确认没有报错后即可 [root@localhost nginx-1.20.1]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
注释: Nginx对进程的控制能力非常强大,可以通过信号指令控制进程。常用的信号有: -QUIT,表处理完当前请求后,关闭进程。 -HUP,表示重新加载配置,也就是关闭原有的进程,并开启新的工作进程。此操作不会中断用户的访问请求,因此可以通过此信号平滑的重启Nginx。 -USR2,用于平滑升级可执行程序。 -WINCH,从容关闭工作进程。
最终平滑升级nginx失败,只能去找项目组沟通,维护服务使用yum升级了,如果有知道解决方法的小伙伴,请在评论区告诉我,谢谢!!!