使用nginx配置http代理

环境

centos 6.5

有网络连接的正常环境

安装nginx

这里使用nginx官方的yum安装(推荐),其它方式安装类似。

rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm

详细参考nginx官方yum源说明 http://nginx.org/en/linux_packages.html#stable

配置ngix

nginx官方出二进制rpm包,其配置沿用redhat/centos的习惯,很清晰明了,配置文件位于 /etc/nginx 目录下,文件如下

[root@iZ11du3hojgZ ~]# ls -lh /etc/nginx/
total 36K
drwxr-xr-x 2 root root 4.0K Nov 30 14:13 conf.d
-rw-r--r-- 1 root root  964 Apr 21  2015 fastcgi_params
-rw-r--r-- 1 root root 2.8K Apr 21  2015 koi-utf
-rw-r--r-- 1 root root 2.2K Apr 21  2015 koi-win
-rw-r--r-- 1 root root 3.9K Apr 21  2015 mime.types
-rw-r--r-- 1 root root  643 Apr 21  2015 nginx.conf
-rw-r--r-- 1 root root  596 Apr 21  2015 scgi_params
-rw-r--r-- 1 root root  623 Apr 21  2015 uwsgi_params
-rw-r--r-- 1 root root 3.6K Apr 21  2015 win-utf

其中主配置文件是 /etc/nginx/nginx.conf,站点配置位于conf.d/ 子目录,每个站点一个文件(默认只有一个default.conf)

直接在default.conf配置文件上修改(改之前可以做个备份,如果就地备份在/etc/nginx/conf.d/目录里,文件名后缀不要是 .conf,否则会被nginx当配置文件加载)

设置站点监听及dns服务器

server{...}节点里,

  1. 修改listen指令,改一下端口,并增加 default 参数,设置成默认nginx站点
  2. 增加resolver 指令,设置域名解析服务器。这里使用dnspod的公共dns服务器如果;国外服务器可以使用google的8.8.8.8等。

location{...}子节点里,

  1. 注释掉root及index两行,当然删除也可以。
  2. 添加一系列proxy_xxx指令。最主要是proxy_pass及proxy_set_header 设置Host头两项,其它是一些参数优化。

设置允许使用代理服务的ip地址。虽然这一步不是必须,但强烈建议配置,避免代理服务器被别人冒用,带宽是宝贵的。不要以为你没公开代理就没人知道,要知道互联网上有无数个代理扫描时刻在偷偷运行着!

 

  1. 设置allow地址白名单。
  2. deny all禁止掉其它所有地址。

 

全部相关配置如下:

server {
    listen       8080 default;
    server_name  localhost;
    resolver 119.29.29.29;
    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;
    .....[略]
    location / {
        #root   /usr/share/nginx/html;
        #index  index.html index.htm;
        proxy_pass $scheme://$host$request_uri;
        proxy_set_header Host $http_host;

        proxy_buffers 256 4k;
        proxy_max_temp_file_size 0;
        proxy_connect_timeout 30;
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 301 1h;
        proxy_cache_valid any 1m;
    }
    .....[略]
    allow 100.200.100.0/24;
    deny all;
}

已知缺陷

不支持https,虽然配置文件里proxy_pass指令使用了可以支持非http协议的通用的形式。事实上这里直接写成http://也是可以的。

参考

nginx proxy模块文档

nginx http access模块文档

CentOS服务器安装后一系列配置参考(CentOS 6.x/CentOS 7)

iptables

CentOS 官方iptables规则:开启ssh端口,允许icmp/ping,不接受其它连接;拒绝FORWARD转发。这是科学的,如果有需要开放的端口再做手工开启。

如果没有默认规则文件 /etc/sysconfig/iptables ,可见自行yum安装 yum install iptables-services,然后 service iptables restartsystemctl restart iptables 加载默认规则,通过iptables命令修改过规则后  service iptables save 保存规则。默认配置文件如下,可参考使用。

# Generated by iptables-save v1.4.7 on Sat Dec 17 10:11:38 2011
# Manual customization of this file is not recommended.
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

sshd: 端口

ssh的服务器端,重要性不需多讲。

其主配置文件 /etc/ssh/sshd_config  (注意不是 /etc/ssh/ssh_config),下面sshd相关配置都在该文件上修改

改一下监听端口,虽然刻意扫描你,还是没的跑,但起码隐藏了一点点。大概13行,Port指令,默认是注释掉的,取消注释,将其后端口号22改成你想要改的,下面以12345为例。注意不要超过65535,不要使用其它已监听端口

Port 12345

[至关重要] iptables里打开相关端口,不要断开当前连接、重启sshd 服务,保存iptables配置到磁盘(以备下次开机时自动生效)

# iptables -I INPUT 4 -m state --state NEW -p tcp --dport 12345 -j ACCEPT

再开一个ssh客户端测试连接,确保改后的端口可以连接。(即使已改过端口,当前连接也还是会保持的)

指定自定义端口的ssh连接: ssh -p 12345  username@your.host.ip

sshd: 用户白名单

限制一下允许通过ssh远程登录的用户名(白名单),可以在文件结尾增加如下一行

AllowUsers user1 user2 user3

其中的user1 user2 user3 是允许通过ssh远程登录的用户,多个用户使用空格分隔。当然,你要事先创建这些普通用户,不然下次就连不上了。

sshd: 禁止root用户直接通过ssh登录

被暴力破解root密码是一件经常遇到的事情,所以严重推荐禁止掉,尤其是使用默认22端口时。增加下一行配置

PermitRootLogin no

日期时间的自动同步

首先确保rdate已安装,使用美国授时中心服务器,加入到crontab,每周日同步一次

# crontab -e
* * * * 0 rdate -s time.nist.gov

详细可参考 linux下日期时间自动同步设置(rdate,ntpdate两种方法)

yum源

开启epel源

CentOS官方yum默认包含了epel-release的yum源,直接安装即可。

yum install epel-release

排除某些rpm包

编辑yum主配置文件 /etc/yum.conf ,在[main] 节点里增加一行exclude指令。比如启用第三方内核时,运行yum更新时,若kernel*有更新,默认内核就会变成官方内核;为避免这个麻烦,可以把kernel*包从yum更新中排除掉。排除多个包可以空格隔开列在同一行,示例如下

exclude=kernel* httpd*

nginx

如果使用nginx的话,可以使用nginx的官方yum源。当然里面只有nginx,没有别的包,所以不会破坏centos原装包的依赖关系。创建/etc/yum.repos.d/nginx.repo内容如下

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key

详细参考nginx官方yum源说明 

 

SELinux

这货很强悍,然而有时也很麻烦,尤其是不够熟的时候,可以考虑关闭,配置在文件 /etc/sysconfig/selinux 中设置 SELINUX=disabledSELINUX=permissive

Grub 2 及第三方内核相关的设置

CentOS 7的Grub2 改变有点大,设置被拆到个文件中,比如 /boot/grub2/grub.cfg, /etc/default/grub/boot/grub2/grubenv 等。注意不要手工编辑grub.cfg。

如果使用的第三方内核,要注意指定默认启动的内核。默认情况下/etc/default/grub里设置了 GRUB_DEFAULT=saved ,要通过/boot/grub2/grubenv指定,但也不要手工修改该文件,而是使用 grub2-set-default 命令的设置。如下三行 1) 列出grub.cfg里的menuentry名称,  2) 设置默认项 grub2-set-default   3) 查看grubenv确认默认项saved_entry

grep "^menuentry" /boot/grub2/grub.cfg |cut -d "'" -f2
grub2-set-default "{menuentry 名称}"
grub2-editenv list

Grub2 参考CentOS 官方文档: https://wiki.centos.org/zh/HowTos/Grub2

开启BBR

实体机/KVM/Xen的VPS下,使用第三方内核开启BBR

本节适用实体机或KVM、Xen虚拟化下的VPS(此方法不支持OpenVZ)。CentOS7官方内核较老,不支持BBR,可使用 ELRepo Project 预编译的内核。其中rpm包url可能会不定期更新,以官方最新为准。(另CentOS6可使用Fedora Copr上项目kernel-el6/

rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
yum install https://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm
yum --enablerepo=elrepo-kernel install kernel-ml -y

参考上节Grub2默认内核做设置,完成后重启,确认内核生效无误。然后再继续。这里最好。

echo 'net.core.default_qdisc=fq' | tee -a /etc/sysctl.conf
echo 'net.ipv4.tcp_congestion_control=bbr' | tee -a /etc/sysctl.conf
sysctl -p

完成后,下面命令确认生效

sysctl net.ipv4.tcp_available_congestion_control
sysctl -n net.ipv4.tcp_congestion_control
lsmod | grep bbr

其输出应该是 net.ipv4.tcp_available_congestion_control = bbr cubic renobbr 及 tcp_bbr 16384 0 (后一行输出的数字可能不同)。

至此bbr启用完成。但,强烈推荐,参考前节“排除某些rpm包”,把kernel* 包从yum更新中排除掉;否则,下次yum更新后,grub默认内核将换成centos官方内核,bbr就没了。

详细可参看 https://www.vultr.com/docs/how-to-deploy-google-bbr-on-centos-7

魔改版BBR(OpenVZ VPS下可用)

基于OpenVZ的 VPS上面方法不支持,得使用魔改版BBR,要求CentOS 7以上(事实上CentOS 6(x64)也可以,但必须升级glibc),一键安装脚本,照提示操作即可。

curl https://raw.githubusercontent.com/linhua55/lkl_study/master/get-rinetd.sh | bash

运行中会提示输入端口号,如有多个端口号用空格隔开(不支持端口段)。如需要增减端口,可修改配置文件 /etc/rinetd-bbr.conf

详细参看作者的github项目

MySQL-Server

配置参考 一份生产环境下MySQL服务配置优化参考样本 (请按硬件及负载酌情修改)

备份脚本,加入到crontab中,定时执行。注意其中备份存储目录、待备份数据库列表、及备份用户账号密码

#!/bin/bash
# Program:
#      auto backup mysql database
# History:
# 2012/05/14    fengyqf First release
#backup folder, with the last slash "/"
backup_folder="/home/user/backup/mysql/"
filename=`date +_%Y%m%d_%N`

for db in db1 db2 db3
do
mysqldump -hlocalhost --opt -e --max_allowed_packet=1048576 --net_buffer_length=16384 -uroot -pYourMysqlRootPassword $db |gzip > $backup_folder$db$filename.sql.gz
done

其它置参考

ulimit, 文件描述符 http://www.path8.net/tn/archives/2024

sysctl, 内核优化 #TODO#

 

生产环境下数据库服务器备份策略参考

定期自动备份,备份文件很频繁,需要定期(1-2个月为宜)清理一些过于频繁的,然后做归档

暂定清理2个月前的备份,清理后,将保留的移到归档目录里,长期保留
暂定每个月保留两份,1日及16日左右
两个月内的备份,全部保留,以备不时之需

长期保留的归档,可以视情况再做精简清理。
定期选择部分下载异地备份

php版本(5.3,5.5,7.0)及运行模式(fast-cgi/fpm,apache模块)之间性能对比测试

php 7.0发布在即,一直以来有传言说php7性能有飞跃,于是做了一个测试。

测试环境

硬件  虚拟机2G内存
OS  CentOS 6.7 (kernel 2.6.32-573.7.1.el6.x86_64)
Web  Apache/2.2.15 (centos 6自带)

php版本选择

5.3.3, CentOS 6自带的版本
5.3.29, 官方5.3分支的最后一个版本,用于跟apache模块做对比
5.6.15,
7.0.0beta3

除了第一个CentOS自带5.3.3是apache模块之外,全部跑在fast-cgi (php-fpm) 模式下,通过apache模块mod_proxy_fcgi整合在apache中(整合方式)。每个版本配置一个虚拟站点,域名分别为 a.dom, b.com... 。

php编译参数

三个自编译版本的编译参数如下(在 /usr/loca 目录下,分别安装到子目录里)

'./configure' '--enable-fpm' '--prefix=/usr/local/php53' '--with-config-file-path=/usr/local/php53/etc' '--with-config-file-scan-dir=/usr/local/php53/etc/php.d' '--enable-exif' '--with-gd' '--with-mysql' '--with-mysqli' '--with-pdo-mysql'

'./configure' '--enable-fpm' '--prefix=/usr/local/php56' '--with-config-file-path=/usr/local/php56/etc' '--with-config-file-scan-dir=/usr/local/php56/etc/php.d' '--enable-exif' '--with-gd' '--with-mysql' '--with-mysqli' '--with-pdo-mysql'

'./configure' '--enable-fpm' '--prefix=/usr/local/php7' '--with-config-file-path=/usr/local/php7/etc' '--with-config-file-scan-dir=/usr/local/php7/etc/php.d' '--enable-exif' '--with-gd' '--with-mysql' '--with-mysqli' '--with-pdo-mysql'

[注] centos自带5.3.3配置参数略,有点长,而且很多模块动态编译成动态加载模块,编译参数里是with-out,所以参数价值不大,故从略。
php7已经移除mysql模块,所以其配置参数里的 --with-mysql 事实上没用,在实际编译中被忽略掉的。

php-fpm配置

php-fpm全部配置成最大20进程,apache也配置成最大20个进程

测试说明

在本机上使用ab测试,减少网络传输的影响,500次连接,并发10,记录 Requests per second(req/s, 以下不再指明),示例

ab -c 10 -n 500 -H "Host: c.dom" http://127.0.0.1/phpinfo.php

[注] 因为使用虚假的域名,所以通过 -H参数指定主机名Host(改host文件也是一样的效果)

测试过程1:phpinfo页面

静态html基准测试,将phpinfo页面的输出保存成html文件,每秒稳定在3000次以上(300并发以下基本上能稳定在3000次,开ab的-k参数的情况下)

(phpinfo页面测试意义其实不大)

版本           次数1       次数2        次数3
---------     --------   --------    ----------
5.3模块:       810         837         774
5.6:          517         635         663
7.0b3:        675         700         638

这里看出php7的性能并不突出,反而apache模块运行效率更高

测试过程2:新安装wordpress文章页

新安装wordpress,其自带的一篇文章页http://127.0.0.1/wordpress/?p=1

版本          次数1        次数2        次数3       次数4
---------    --------    --------    ---------  --------
5.3模块:      7.00        7.06        6.84       6.91
5.6:         7.54        7.55        7.48       4.55
7.0b3:       10.12       10.38       10.14      10.47

[小结]:5.6 较5.3略有增强,但差别很小;但php7较都有显示提高。

测试过程3:wordpress导入一批文章后的文章页

导入一批文章后,该测试里增加php5.3.29的fast-cgi版本

ab -c 10 -n 500 -H "Host: c.dom" http://127.0.0.1/wordpress/?p=6459
版本         次数1      次数2       次数3      次数4      次数5    平均值
---------   ------    -------    --------   -------   -----   -----
5.3模块:     5.76      5.60       5.66       5.64      5.82    5.696
5.3 fpm:    5.86      5.97       5.91       6.11      5.97    5.964
5.6:        6.57      6.62       6.65       7.35      5.49    6.536
7.0b3:      8.73      8.33       9.02       9.00      8.67    8.750

[小结]:延续前面的结果,php7比5.x有30%-50%提升,效果明显。

另外5.3的fastCGI及模块差别可以忽略,似乎不像有人说的fastCGI效率有多高。

php7性能提升幅度,似乎也不像鸟哥Laruence所说的翻倍以上的提升(第45页片子)但30%+的提升,也足够让人欣喜了

测试结论

就前面做的测试来看,php7确实比5.x版本有明显提升,值得在生产环境中部署(暂不考虑兼容性)。然而说前面测试结果来看,

附记*php的后向兼容性

按官方文档所示,php7在语言核心方面,变化几乎忽略。主要是彻底放弃php5.4以来已经声明“过时”的特性。

已知可能有较大影响的是 mysql_* 函数被移除,这就意味着使用mysql_*的一些旧应用将无法在php7上跑!一个可选的解决方案是,使用fastCGI,多php版本共存,迁就这些旧应用。

apache下php版本共存,可以参考CentOS 6.x/apache 2.2下php多版本共存探索(模块及fastcgi)/mod_proxy_fcgi实现

CentOS 6.x/apache 2.2下php多版本共存探索(模块及fastCGI)/mod_fcgi,mod_proxy_fcgi实现

在apache下整合fastCGI模式运行的php-fpm,似乎网上很少相关材料,就连英文版材料也少。只要是php-fpm,基本上都是与nginx搭配。查了一大批相关资料,写本文总结一下。

apache下有多个fastCGI的支持方案:至少有mod_fcgimod_fastcgigit)、mod_proxy_fcgi等。这两个模块都有点老,尤其mod_fastcgi自从2007年以来就没有更新,略掉不谈,事实上没用过用。mod_proxy_fcgi模块是httpd 2.4+的版本正式引入,通过简洁的一行 ProxyPassMatch 指令即可。

mod_fcgi

mod_fcgi模块本身是做fastCGI进程管理的,使用它就不需要使用php-fpm管理进程了。核心配置参数

LoadModule fcgid_module modules/mod_fcgid.so
<VirtualHost *:80>
    DocumentRoot "/var/www/html/site_1"
    ServerName "www.yourhost.com"
    DirectoryIndex index.html index.php
    #php.ini的存放目录,Linux下通常不需要
    #FcgidInitialEnv PHPRC "D:/php"
    # 设置PHP_FCGI_MAX_REQUESTS大于或等于FcgidMaxRequestsPerProcess,防止php-cgi进程在处理完所有请求前退出
    FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 1000
    #php-cgi每个进程的最大请求数
    FcgidMaxRequestsPerProcess 1000
    #php-cgi最大的进程数
    FcgidMaxProcesses 3
    #最大执行时间
    FcgidIOTimeout 600
    FcgidIdleTimeout 600
    #php-cgi的路径
    FcgidWrapper /usr/local/php7/bin/php-cgi .php
    AddHandler fcgid-script .php
    FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 1000
    <Directory "/var/www/html/site_1">
        Options +ExecCGI
    </Directory>
</VirtualHost>

其中粗体着色是必须参数,其它几个Fcgid*指令,是优化之用,这里仅示例,要按实际情况调整数值。具体参看mod_fcgi官方文档

使用mod_fcgid的几个特点

  1. php-fgi进程是由apache模块启动并管理,不需要配置php-fpm
  2. 在php-cig进程以apache用户身份运行,php程序写的文件,其权限为apache用户(而不像php-fpm下写文件为php-fpm用户所有,默认是nobody),这样在目录权限管理方面一致性高些。

mod_fastcgi

虽然CentOS 6.x下是apache 2.2,但所幸已经有人成功移植: https://github.com/ceph/mod-proxy-fcgi 我们可以直接使用;更幸运的是它已经进入epel源,直接yum安装即可;不想匹配epel源的,直接下载rpm包安装也可以(示例 http://mirrors.ustc.edu.cn/epel/6/x86_64/

当然可以重新编译安装apache 2.4, 这样直接有mod_proxy_fcgi可以使用,但这里还是保持原版本不变,省掉编译的工作量。

参考mod_proxy_fcgi官方文档,整合php-fpm的配置指令

ProxyPassMatch "^/myapp/.*\.php(/.*)?$" "fcgi://localhost:9000/var/www/"

语法很简单,跟配置反向代理类似,可以按实际需要做修改。事实上与mod_proxy模块语法一致的,不同处是将http协议改成fcig协议。

以上是apache整合php-fpm模式运行的fastCGI,接下来要对yum安装的php做下配置修改。

yum安装的php配置文件 /etc/httpd/conf.d/php.conf ,其中有如下一行

AddHandler php5-script .php

我们要对不同的站点启用不同的php,上面一行是对全局的.php文件分配给php模块处理,我们把这一行注释掉。而是在每个站点启用不同的php运行模式。

以上即是处理方式。

[已知问题]:裸目录地址转发

有一个困扰的问题没有解决,感觉有点像模块bug:

对于配置了DirectoryIndex index.php的目录,如果其子目录没有index.php,上述ProxyPassMatch还是会做fastCGI转发,这时会看到php-fpm的404响应,而不是apache的响应403页面。但前面的规则并不转发这裸空目录的url,所以感觉像bug

再者就是,对于ProxyPassMatch匹配的目录,apache自动索引功能失效。(当然如果不开启autoindex就无所谓了。生产环境下通常不开启的)

其它,似乎也没有什么严重后果,或者我没还意识到(?)。

解决方法:每个目录下,都放置一个index.html,避免fpm-php处理空请求

 

新版本firefox(如ESR 38+/45+)下live http headers扩展重发请求功能异常修正版

[20160803更新] 安装扩展 Live HTTP Headers (clone) 即可. https://addons.mozilla.org/zh-Cn/firefox/addon/live-http-headers-clone/

感谢该clone版作者的贡献,同时也感谢原版作者的贡献!

------------------------ 下面的文章内容已经过时,仅供参考-----------------

live http headers扩展是一个神器,彪悍简洁好用。然而似乎用户并不那么多,导致维人员看上去并不那么上心,出过几次无法正常使用的bug。本文是本人探索积累下来的经验。

firefox 38左右某版本下解决方案

[20151105]

firefox下的live http headers扩展的功能就不说了,因为firefox版本升级,在某个版本(可能是32左右)的某些改变,该扩展的重发请求功能坏掉了,查看该扩展的官方也有相应的bug报告

从这一页面里https://www.mozdev.org/bugs/show_bug.cgi?id=25831,有国外高手回复说的修正版,修正版在 http://rghost.net/58012556 可以直接下载,然后在通过firefox菜单-文件-打开,浏览到该xpi包安装

为防失效,转来一份 livehttpheaders,是zip压缩过的(wordpress限制文件格式),下载后解压缩后再按上法安装

firefox 45左右某版本下解决方案

[20160708]

firefox 某个版本强制要求扩展的签名机制,至少ESR 45起上面xpi文件已经不能安装了,提示说“似乎已损坏”。

经过探索,发现可以将上述xpi文件解压后的chrome/livehttpheaders.jar文件的替换firefox用户目录里相应的文件即可。不过,firefox重启后,签名验证会再次禁止扩展;换回去再改一次好了。虽然很麻烦,但勉强能用。

  • livehttpheaders.jar 文件可以直接从这里下载livehttpheaders__unpacked-file-livehttpheaders-jar,是zip压缩过的(wordpress限制文件格式),使用前先解压。
  • 我的firefox用户目录里相应位置在,具体请自行寻找一下  C:\Users\Administrator\AppData\Roaming\Mozilla\Firefox\Profiles\d1cain74.default\extensions\{8f8fe09b-0bd3-4470-bc1b-8cad42b8203a}\chrome

由此判断,firefox扩展的签名验证机制,只是在扩展安装及firefox启动时验证,firefox运行中是不检查的。

live http headers重发请求功能的示例

live_http_headers_replylive_http_headers_reply