利用Nginx的auth_basic模块密码保护WordPress后台目录

有时候WordPress会遭遇到一些别有用心的人尝试访问wp-admin进行登录,这时候如果对后台目录的访问进行一个限制,就能防止一部分恶意行为。那么今天就利用一下Ngnix的ngx_http_auth_basic_module模块,进行一个简单的访问验证。

默认情况下Nginx已经安装编译了这个模块,我们可以通过几步就可以完成对指定目录的保护。

第一步:创建密码文件

登录ssh到你想要存放密码文件的目录,用Vi建立文本( 按 i 插入模式 :wq 保存并退出)

格式为 用户名:密码

建立完成后,记得设置一下文件权限为400

[root@izyi5 www]# vi my.pass
test:123456
~
:wq
[root@izyi5 www]#chmod 400 my.pass

第二步:修改Nginx配置

仿照下面代码修改站点的Nginx配置文件

server{
server_name  www.blog67.com blog67.com;

index index.html index.php;
root /data/site/www.blog67.com;

#添加auth_basic验证代码
#location后为需要保护的目录路径,此处以WP后台为例
#auth_basic为提示文本
#auth_basic_user_file为密码文件路径

location /wp-admin/
{
auth_basic "Test For blog67.com";
auth_basic_user_file /www/my.pass;
}

}

注意:密码文件路径一定要正确,否则会一直出现403错误

然后重载Nginx配置,执行

nginx -s reload

效果

现在可以访问一下后台看看,出现下图:

未分类

成功~

Nginx报No input file specified错误解决方法

由于某些原因,服务器重启了,然而重启之后,再次访问居然报404错了:No input file specified.nginx配置没有动过,怎么会无缘无故出现这个问题呢?

这个其实是很常见的错误,百度随便一搜就有好多的答案,解决问题的方案都是重新配置nginx,使它能正确找到php文件。这个也是我早就知道的,既然发了这篇文章,就说明用那些方法不能解决,或者就不是nginx配置方面的问题。那么还有什么原因造成这个现象呢?

nginx做了虚拟主机配置,访问其他的站点,更奇怪的是有些可以访问,有些也报404.总结了下规律,发现如果index到html等静态文件,就没有问题,如果index到php文件,那就不行了。

不知道什么原因的话,那就控制变量一步一步来吧。

首先在根目录下建一个文件:a.php,写个简单的输出hello world的程序。

<?php

echo "hello world" ;

然后试着访问下https://chenqinghe.com/a.php。不行,还是报404.

再建个文件:1.txt,随便打些内容,再次访问。正常返回了!

这就奇怪了,nginx配置没有改过,肯定是能够找到php文件的,那为什么还不行呢?

又搜了下,发现了这篇文章:Nginx报 No input file specified. 的问题解决之路(https://m.aliyun.com/yunqi/articles/34240)

我立马看了下根目录下面有没有.user.ini文件,让人失望的是,没有发现……

无奈之下想到了杀手锏strace,之前用来追踪mysql长连接时用过,可以看进程的系统调用。那用strace追踪一下看看咯,设置php-fpm为静态模式,子进程数量固定为1,然后用strace追踪这个子进程,然后访问网址,观察调用情况。

sudo strace -p 2773 -s 1000 //绑定pid为2773的进程,设置字符串长度为1000

然后发现了些猫腻:

未分类

原来是open_basedir捣的鬼!!这个php.ini中的设置会把打开文件目录限定在设置的目录内,如上图红框内所示,不在这个目录里,就不允许访问,所以会报这个错。在php.ini中把这项注释了之后,正常了!

那么为什么重启服务器之后会这样呢?后来仔细想想,之前在用/dev/urandom生成真随机数的时候设置的,那时候设置完了之后只在命令行下执行了php的命令,也就是只用了cli这个sapi,并没有重启php-fpm,所以当时没有发现这个问题,这次重启服务器之后,这个问题就暴露了出来,果然是个大坑啊……

这篇文章主要记录了排查错误的方式,更多的时候这些排查方式比解决方案更有用,所以记录下来。

配置nginx支持TLS 1.3

几个月前,我在升级本博客所用 Nginx 时,顺手加上了对 TLS 1.3 的支持,本文贴出详细的步骤和注意事项。有关 TLS 1.3 的介绍可以看 CloudFlare 的这篇文章:An overview of TLS 1.3 and Q&A。需要注意目前 Chrome 和 Firefox 支持的是 TLS 1.3 draft 18,暂时不要用在生产环境。

安装依赖

我的 VPS 系统是 Ubuntu 16.04.3 LTS,如果你使用其它发行版,与包管理有关的命令请自行调整。

首先安装依赖库和编译要用到的工具:

sudo apt-get install build-essential libpcre3 libpcre3-dev zlib1g-dev unzip git

获取必要组件

nginx-ct 和 ngx-brotli 与本文主题无关,不过都是常用的 Nginx 组件,一并记录在这里。

nginx-ct

nginx-ct 模块用于启用 Certificate Transparency 功能。直接从 github 上获取源码:

wget -O nginx-ct.zip -c https://github.com/grahamedgecombe/nginx-ct/archive/v1.3.2.zip
unzip nginx-ct.zip

ngx_brotli

本站支持 Google 开发的 Brotli 压缩格式,它通过内置分析大量网页得出的字典,实现了更高的压缩比率,同时几乎不影响压缩 / 解压速度。
以下是让 Nginx 支持 Brotli 所需准备工作,这些工作是一次性的。首先安装 libbrotli:

sudo apt-get install autoconf libtool automake

git clone https://github.com/bagder/libbrotli
cd libbrotli

# 如果提示 error: C source seen but 'CC' is undefined,可以在 configure.ac 最后加上 AC_PROG_CC
./autogen.sh

./configure
make
sudo make install

cd  ../

默认 libbrotli 装在 /usr/local/lib/libbrotlienc.so.1,如果后续启动 Nginx 时提示找不到这个文件,那么可以把它软链到 /lib 或者 /usr/lib 目录。如果还有问题,请参考这篇文章查找解决方案。

接下来获取 ngx_brotli 源码:

git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli

git submodule update --init

cd ../

OpenSSL

为了支持 TLS 1.3,需要使用 OpenSSL 1.1.1 的 draft-18 分支:

git clone -b tls1.3-draft-18 --single-branch https://github.com/openssl/openssl.git openssl

编译并安装 Nginx

接着就可以获取 Nginx 源码,编译并安装:

wget -c https://nginx.org/download/nginx-1.13.3.tar.gz
tar zxf nginx-1.13.3.tar.gz

cd nginx-1.13.3/

./configure --add-module=../ngx_brotli --add-module=../nginx-ct-1.3.2 --with-openssl=../openssl --with-openssl-opt='enable-tls1_3 enable-weak-ssl-ciphers' --with-http_v2_module --with-http_ssl_module --with-http_gzip_static_module

make
sudo make install

enable-tls1_3 是让 OpenSSL 支持 TLS 1.3 的关键选项;而 enable-weak-ssl-ciphers 的作用是让 OpenSSL 继续支持 3DES 等不安全的 Cipher Suite,如果你打算继续支持 IE8,才需要加上这个选项。

除了 http_v2 和 http_ssl 这两个 HTTP/2 必备模块之外,我还额外启用了 http_gzip_static,需要启用哪些模块需要根据自己实际情况来决定。
以上步骤会把 Nginx 装到 /usr/local/nginx/ 目录,如需更改路径可以在 configure 时指定。

WEB 站点配置

在 Nginx 的站点配置中,以下两个参数需要修改:

ssl_protocols              TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # 增加 TLSv1.3
ssl_ciphers                TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;

包含 TLS13 是 TLS 1.3 新增的 Cipher Suite,加在最前面即可;如果你不打算继续支持 IE8,可以去掉包含 3DES 的 Cipher Suite。

本博客完整的 Nginx 配置,请打开 (https://imququ.com/post/my-nginx-conf.html) 查看。

验证是否支持 TLS 1.3

目前最新版 Chrome 和 Firefox 都支持 TLS 1.3,但需要手动开启:

  • Chrome,将 chrome://flags/ 中的 Maximum TLS version enabled 改为 TLS 1.3(Chrome 62 中需要将 TLS 1.3 改为 Enabled (Draft),感谢 @TsuranSonoda 指出);

  • Firefox,将 about:config 中的 security.tls.version.max 改为 4;

本博客多次推荐的 Qualys SSL Labs’s SSL Server Test(https://www.ssllabs.com/ssltest/index.html) 也支持验证服务端是否支持 TLS 1.3,非常方便,继续推荐。

设置tomcat nginx上传文件大小限制

一、关于在tomcat在server.xml的配置文件上传大小20M的限制 – maxPostSize=”20971520″

<Connector port="8080" protocol="HTTP/1.1"
                           maxThreads="200" 
                           minSpareThreads="25" 
                           maxSpareThreads="100"
                           acceptCount="200"
                           maxPostSize="20971520"
                           connectionTimeout="30000"
                           enableLookups="false"
                           disableUploadTimeout="true"
                           compression="on"
                           compressableMimeType="text/html,text/xml,text/plain,text/css,
                           text/javascript,text/json,application/x-javascript,
                           application/javascript,application/json"
                       noCompressionUserAgents="gozilla, traviata"
               redirectPort="8443" />

二、在nginx的nginx.conf的配置文件上传大小为20M – client_max_body_size 20m;

location /gw/file/upload {
            proxy_pass http://127.0.0.1/upload;
            proxy_redirect  off;
            proxy_set_header        Host    $http_host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   Cookie $http_cookie;
            client_max_body_size   20m;
}

使用nginx virtualenv uWSGI配置django运行环境

升级并安装 pip

sudo apt-get update
sudo apt-get install python-pip

安装虚拟环境

sudo pip install virtualenv virtualenvwrapper

加入到环境变量中

当前用户目录下的 Env为虚拟环境存放的目录

echo "export WORKON_HOME=~/Env" >> ~/.bashrc
echo "source /usr/local/bin/virtualenvwrapper.sh" >> ~/.bashrc

激活配置

source ~/.bashrc

创建虚拟环境

环境名为:firstsite

在用户当前目录下创建 Django工程

cd ~
django-admin.py startproject firstsite

django 的初始化

cd ~/firstsite
./manage.py migrate
./manage.py createsuperuser

Django静态文件配置

nano firstsite/settings.py
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
./manage.py collectstatic

安装 uWSGI

sudo apt-get install python-dev
sudo pip install uwsgi

测试是否能够正常访问 django 项目

  • http 指定进程端口8080
  • home指定虚拟环境目录
  • chdir指定 项目工程所在目录
uwsgi --http :8080 --home /home/pi/Env/firstsite --chdir /home/pi/firstsite -w firstsite.wsgi

创建 uwsgi 的配置文件

sudo mkdir -p /etc/uwsgi/sites
cd /etc/uwsgi/sites

uwsgi 的配置相关内容(重点)

[uwsgi]
project = firstsite
base = /home/pi

chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application

master = true
processes = 5

socket = %(base)/%(project)/%(project).sock
chmod-socket = 666
vacuum = true

启动守护进程

vim /etc/systemd/system/uwsgi.service

[Unit]
Description=uWSGI Emperor service
After=syslog.target

[Service]
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target

重载守护进程的配置信息

sudo systemctl daemon-reload

系统重启后uwsgi守护进程自动重启

sudo systemctl enable uwsgi

启动uwsgi进程

sudo systemctl start uwsgi

nginx 的安装

sudo apt-get install nginx

nginx的配置

sudo nano /etc/nginx/sites-available/firstsite
server {
    listen 80;
    server_name firstsite.com www.firstsite.com;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/pi/firstsite;
    }

    location / {
        include         uwsgi_params;
        uwsgi_pass      unix:/home/pi/firstsite/firstsite.sock;
    }
}

nginx配置生效

sudo ln -s /etc/nginx/sites-available/firstsite /etc/nginx/sites-enabled

检查配置

sudo service nginx configtest

重启nginx

sudo service nginx restart

非 debug 模式

非 debug 模式需要重启uwsgi 服务

sudo systemctl restart uwsgi

Nginx自定义404页面3种方法

未分类

一个网站项目,肯定是避免不了404页面的,通常使用Nginx作为Web服务器时,有以下集中配置方式,一起来看看。

第一种:Nginx自己的错误页面

Nginx访问一个静态的html 页面,当这个页面没有的时候,Nginx抛出404,那么如何返回给客户端404呢?

看下面的配置,这种情况下不需要修改任何参数,就能实现这个功能。

server {

listen      80;

server_name  www.test.com;

root   /var/www/test;

index  index.html index.htm;

location / {

}

# 定义错误页面码,如果出现相应的错误页面码,转发到那里。

error_page  404 403 500 502 503 504  /404.html;

# 承接上面的location。

location = /404.html {

# 放错误页面的目录路径。

root   /usr/share/nginx/html;

}

}

第二种:反向代理的错误页面

如果后台Tomcat处理报错抛出404,想把这个状态叫Nginx反馈给客户端或者重定向到某个连接,配置如下:

upstream www {

server 192.168.1.201:7777  weight=20 max_fails=2 fail_timeout=30s;

ip_hash;

}

server {

listen       80;

server_name www.test.com;

root   /var/www/test;

index  index.html index.htm;



location / {

if ($request_uri ~* ‘^/$’) {

rewrite .*   http://www.test.com/index.html redirect;

}

# 关键参数:这个变量开启后,我们才能自定义错误页面,当后端返回404,nginx拦截错误定义错误页面

proxy_intercept_errors on;

proxy_pass      http://www;

proxy_set_header HOST   $host;

proxy_set_header X-Real-IP      $remote_addr;

proxy_set_header X-Forwarded-FOR $proxy_add_x_forwarded_for;

}

error_page    404  /404.html;

location = /404.html {

root   /usr/share/nginx/html;

}

}

第三种:Nginx解析php代码的错误页面

如果后端是php解析的,需要加一个变量

在http段中加一个变量 fastcgi_intercept_errors on 就可以了。

指定一个错误页面:

error_page    404  /404.html;

location = /404.html {

root   /usr/share/nginx/html;

}

指定一个url地址:

error_page 404  /404.html;

error_page 404 = http://www.test.com/error.html;

Typecho Nginx 开启https(解决其他页面404问题)

本文假设你已经申请好了证书,并已经配置到服务器

1、在项目根目录下的配置文件config.inc.php中添加如下代码,让后台访问https资源,不加的话后台登录仍然访问http;

define('__TYPECHO_SECURE__',true);

2、nginx配置文件中,在你解析443端口的server中,在localhost中添加如下代码,地址带参数跳转,不加会导致其他页面404;

try_files $uri $uri/ /index.php?$query_string;
if (!-e $request_filename){  
    rewrite ^/(.*) /index.php last;  
} 

例如:

location ~ .*.php(/.*)*$ {
    try_files $uri $uri/ /index.php?$query_string;
    if (!-e $request_filename){
        rewrite ^/(.*) /index.php last;
    }
   ...
}

3、在项目代码中header.php中加入如下代码,默认访问https(可选);

if ($_SERVER["HTTPS"] <> "on")
{
    $xredir = "https://".$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
    header("Location: ".$xredir);
}

使用Docker快速搭建Nginx PHP-FPM环境

背景

在上一周笔者对docker了解,仅限于这样认知:它能替代虚拟机,并且比虚拟机更省资源。

在老师和同事的感染下,感觉不学习docker好像就不能在IT圈混一样,于是,开始涌入Docker的大潮中。但万事开头难,听了同事的推荐,看了宁皓网的基础的视频之后感觉仅是对基本的命令进行了了解。但是真拿出来用还是不够用的,于是开始搜罗更

重资料,学习搭建LNMP环境。
终于功夫不负有心人,在今天终于是实验成功了,特此写下这篇笔记,为后来人提供一个示例。

实战

1、下载nginx官方镜像和php-fpm镜像

docker pull nginx
docker pull bitnami/php-fpm

未分类

笔者未进行更改docker源,依然是官方源。
当然,你可以使用中国源。

2、使用php-fpm镜像开启php-fpm应用容器

docker run -d --name myFpm -p  -v /var/www/html:/usr/share/nginx/html bitnami/php-fpm
  • -d : 该参数为后台运行之意
  • -v : 指定宿主机与容器的映射关系。/var/www/html为宿主机的项目目录(自定义的),/usr/share/nginx/html为nginx服务器项目默认的路径。

3、使用nginx镜像开启nginx应用容器

docker run -d --name myNginx -p 8080:80 -v /var/www/html:/usr/share/nginx/html nginx
  • -p : 该参数设置端口对应的关系。所有访问宿主机8080端口的URL会转发到nginx容器的80端口。

4、查看对应的IP信息

  • 首先查看是否启动成功
docker ps -a

未分类

可以看到,上述在STATUS一栏中显示UP,其含义为正在运行。

  • 查看IP信息
docker inspect myFpm | grep "IPAddress"

未分类

5、修改nginx的相关配置

在容器中是没有vim命令的,所以不能在容器中直接修改配置文件。所以我们必须通过变通的方式去解决这个问题,否则只能在每个容器中安装vim。

  • 首先登录到对应的容器中,查看配置信息路径,这在之后修改时会用到。
docker exec -it myNginx /bin/bash

未分类

  • -i : –interactive,交互模式。
  • -t : –tty,开启一个伪终端。
  • /bin/bash : 必须写,否则会报错。这是开始伪终端时,进入bash界面,也就是命令行界面。

  • 查看对应的配置文件位置

/etc/nginx/conf.d/default.conf

未分类

  • 退出命令行,不要使用exit,因为exit会让容器停止。这里使用ctrl + p + q来退出容器。

  • 使用专用的复制命令将配置文件复制到宿主机,然后在宿主机进行编辑(这就是变通的方法)

docker cp myNginx:/etc/nginx/conf.d/default.conf ./default.conf

这里用到了上一步查询到的配置文件路径信息

  • 在宿主机修改配置文件的php部分,内容如下:
location ~ .php$ {
   fastcgi_pass   172.17.0.2:9000;
   fastcgi_index  index.php;
   fastcgi_param  SCRIPT_FILENAME  /usr/share/nginx/html$fastcgi_script_name;
   fastcgi_param  SCRIPT_NAME      $fastcgi_script_name;
   include        fastcgi_params;
}
  • 再次使用复制命令将其复制到容器中,然后再次进入容器中,将nginx配置文件重新载入
docker cp ./default.conf myNginx:/etc/myNginx:/etc/nginx/conf.d/default.conf
  • 进入到nginx容器中重新载入配置文件
docker exec -it myNginx /bin/bash
service nginx reload

成功了

我看了一下,用到的模块还都有。

未分类

未分类

未分类

未分类

Centos 7系统开启nginx的HTTP/2教程

  • HTTP 2.0即超文本传输协议 2.0,是下一代HTTP协议。是由互联网工程任务组(IETF)的Hypertext Transfer Protocol Bis (httpbis)工作小组进行开发。是自1999年http1.1发布后的首个更新。

  • HTTP/2 协议是从 SPDY 演变而来,SPDY 已经完成了使命并很快就会退出历史舞台(例如 Chrome 将在「2016 年初结束对 SPDY 的支持」;Nginx、Apache 也已经全面支持 HTTP/2 ,并也不再支持 SPDY)。一般的大家把 HTTP2 简称为 h2,尽管有些朋友可能不怎么愿意,但是这个简称已经默认化了,特别是体现在浏览器对 HTTP2 都是这个简写的。普通的 HTTPS 网站浏览会比 HTTP 网站稍微慢一些,因为需要处理加密任务,而配置了 h2 的 HTTPS,在低延时的情况下速度会比 HTTP 更快更稳定!

未分类

从 Nginx 1.9.5 开始,http_v2_module 已经替换了 ngx_http_spdy_module,建议直接去 Nginx 官网(https://www.91linux.org/go/?url=http://nginx.org/) 下载最新源码包

  • 要开启HTTP/2需要nginx版本在1.9.5以上且需要openssl版本在1.0.2以上编译。
  • http2.0只支持开启了https的网站

OpenSSL

由于 OpenSSL 是系统基础库,大量其他软件都对它有依赖,如果直接升级系统自带的 OpenSSL,很容易引发各种问题。更为稳妥的做法是在编译 Web Server 时自己指定 OpenSSL 的位置。也就是通过 –with-openssl 指定了新版 OpenSSL 源码路径,这样编译出来的 Nginx 就会用上最新的 OpenSSL 库。

本站目前使用 OpenSSL 1.0.2l:

wget -O openssl.tar.gz -c https://github.com/openssl/openssl/archive/OpenSSL_1_0_2l.tar.gz
tar zxf openssl.tar.gz
mv openssl-OpenSSL_1_0_2l/ openssl

打上 ChaCha20/Poly1305 补丁:

git clone https://github.com/cloudflare/sslconfig.git
cd openssl
patch -p1 < ../sslconfig/patches/openssl__chacha20_poly1305_draft_and_rfc_ossl102j.patch
cd ../

编译并安装 Nginx

接着就可以获取 Nginx 源码,并打上 Dynamic TLS Records 补丁:

wget -c https://nginx.org/download/nginx-1.11.13.tar.gz
tar zxf nginx-1.11.13.tar.gz

cd nginx-1.11.13/
patch -p1 < ../sslconfig/patches/nginx__1.11.5_dynamic_tls_records.patch

cd ../

编译和安装:

cd nginx-1.11.13/
./configure --user=www --group=www --prefix=/usr/local/nginx --with-openssl=../openssl --with-http_v2_module --with-http_ssl_module  --with-http_gzip_static_module --with-http_stub_status_module --with-http_sub_module

make
sudo make install

除了 http_v2 和 http_ssl 这两个 HTTP/2 必备模块之外,我还额外启用了 http_gzip_static,需要启用哪些模块需要根据自己实际情况来决定(注:从 Nginx 1.11.5 开始,ipv6 模块已经内置,故 –with-ipv6 配置项已被移除)。

以上步骤会把 Nginx 装到 /usr/local/nginx/ 目录,如需更改路径可以在 –prefix指定。

设置nginx启动脚本

编辑 vi /lib/systemd/system/nginx.service 文件,没有创建一个 touch nginx.service 然后将如下内容根据具体情况进行修改后,添加到nginx.service文件中:

[Unit]
Description=nginx
After=network.target remote-fs.target nss-lookup.target

[Service]

Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

设置开机启动:systemctl enable nginx
立即启动:systemctl start nginx

配置HTTP/2

配置Nginx开启http 2.0特别简单,只要在Nginx配置文件中找到你要开启http2.0的域名server模块,然后将 listen 443 ssl;改成 listen 443 ssl http2; 即可。

server {
    listen 443 ssl http2 default_server;

    ssl_certificate    server.crt;
    ssl_certificate_key server.key;
    ...
}

保存配置文件之后,重启或重载Nginx即可生效:systemctl restart nginx