Nginx 反代 upstream sent too big header

今天突然几个站点打不开了,出现了502 错误,赶紧打开nginx error log, 发现了这个错误:

upstream sent too big header while reading response header from upstream, client: XX.XX.XX.XX

这个错误很明显,是nginx proxy buffer 不够了,解决的办法很简单,直接在http block 里面添加如下命令即可:

proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;

添加完毕重启即可解决上述问题.

同时这也说明了在监控中,不仅要检查nginx,mysql 的程序运行情况,也要检查http status, 只有200的情况是可以接受的

vlan 于 trunk 打标签的过程

交换机内部的对vlan tag的处理有以下几种情况:(按照数据包的转发方向)

1、从Access端口进入,然后从Access端口发出;则进入是带上vlan tag,发出时去掉vlan tag;

2、从Access端口进入,然后从Trunk端口发出;则进入时带上vlan tag,发出时保留vlan tag;

3、从Trunk端口进入,然后从Trunk端口发出;则vlan tag无变化,进来什么样出去还是什么样;

4、从Trunk端口进入,然后从Access端口发出;则进入时无变化,出去时去掉vlan tag;

其实很简单,从access口出来的都是不带tag的,从trunk口出来,都是带tag的

trunk的作用是可以让多个vlan通过,原理是对不同的vlan打上不同的标签以区分不同的vlan的数据帧

monit 在 centos 7 和debian 8, debian 9下的使用

在老的centos 6 和 debian 7 中,monit 是通过对 pid 的监控来判断程序是否die 或者有问题的, 但是在 centos 7 和 debian 8 和debian 9下,只要service 不是以forking 的形式启动,systemd 就不会让service 创建 pid file,即使你在service 的配置文件中创建了 PidFile 的命令,这个命令是会被忽略的

因为在由systemd 控制的linux 系统中,monit 无法通过pid 的形式来监控程序,在这里我们就需要用到monit 的的match 命令,比如说nginx 来可以match ‘nginx’, 来完成对nginx 的监控

CentOS 上使用 NFS 的教程以及介绍

NFS 可以把NFS server 上的文件及文件共享给NFS client 服务器

两个概念,NFS Server(Master) 和 NFS Client

NFS Server 可以把本服务器上的文件和文件夹共享给NFS Client, NFS Client 可以在共享的文件和文件夹上进行读写操作,并且实时返回给NFS Master

NFS Server 一般作为存储服务器,常见为使用RAID 5 和 RAID 10 的存储服务器,容量比较大. 对于一些图片站和网盘站点,网站所在的服务器一般为NFS Client,NFS Client 把图片和文件直接存储在NFS Server上

为了方便对NFS进行user id 和 group id 进行统一管理,我们一般需要NFS Server 和 NFS Client 使用同一种操作系统, 比如说centos 和 centos. 当然了,分别使用不同的操作系统,比如说centos 和 debian 也是可以的,就是有点麻烦而已.

下面进行详细的安装步骤:

无论是CentOS 6 和 CentOS 7, 安装步骤基本都一致,这里推荐CentOS 7. RHEL系的操作系统越新越好用

服务器配置:

NFS Server Hostname: server.unixmen.local
NFS Server IP Address: 192.168.1.101/24

 

NFS Client Hostname: client.unixmen.local
NFS Client IP Address: 192.168.1.102/24

NFS服务器端配置:

CentOS 6:

yum install nfs-utils nfs-utils-lib

chkconfig nfs on 
service rpcbind start
service nfs start

CentOS 7:

yum install nfs-utils nfs-utils-lib

systemctl enable rpcbind
systemctl enable nfs-server
systemctl enable nfs-lock
systemctl enable nfs-idmap

systemctl start rpcbind
systemctl start nfs-server
systemctl start nfs-lock
systemctl start nfs-idmap

因为CentOS 7 在系统上改了好多,所以安装稍微有点不同,其实都是同一个库

下面配置共享目录,假设我们需要共享/home 目录给client

vi /etc/exports

然后添加下面:

/home  192.168.0.102 (rw,sync,no_root_squash,no_subtree_check)

参数的解释:

rw: 这个选项允许client server 在共享目录上进行读和写的操作

ro: 只读

sync: 将数据同步写入内存缓冲区与磁盘中,效率低,但可以保证数据的一致性;

no_root_squash: 登入 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分享的目录来说,他就具有 root 的权限!

root_squash: 在登入 NFS 主机使用分享之目录的使用者如果是 root 时,那么这个使用者的权限将被压缩成为匿名使用者,通常他的 UID 与 GID 都会变成 nobody 那个系统账号的身份

all_squash: 将远程访问的所有普通用户及所属组都映射为匿名用户或用户组 (nfsnobody)

no_all_squash: 与all_squash 相反, 默认配置

anonuid=xxx: 将远程访问的所有用户都映射为匿名用户,并指定该用户为本地用户(UID=xxx);
anongid=xxx: 将远程访问的所有用户组都映射为匿名用户组账户,并指定该匿名用户组账户为本地用户组账户(GID=xxx);

这里需要注意的, NFS 进行映射的时候,用的是uid 和 gid, 而非是用户名和group 的名字. 所以通常的做法是, 在NFS server 和 NFS client 上使用相同的用户名和用户组,以及相同UID和 GID

相同的用户名和用户组这个好解决, UID 和 GID不同的话,需要update uid 和 gid以使他们相同. 在centos 上我们经常使用军哥的lnmp,用户名和用户组都为www,加入uid 为501, gid 为501, 则我们可以用

(rw, sync, no_subtree_check, all_squash, anonuid=501, anongid=501)

async: 将数据先保存在内存缓冲区中,必要时才写入磁盘;

subtree: 若输出目录是一个子目录,则nfs服务器将检查其父目录的权限(默认设置);
no_subtree:即使输出目录是一个子目录,nfs服务器也不检查其父目录的权限,这样可以提高效率;

配置完成以后,我们需要export这个配置来时他生效:

exportfs -a

下面我们需要配置NFS Client

安装NFS:

yum install nfs-utils nfs-utils-lib

mount 共享目录给 /home

mount -t nfs 192.168.1.101:/home /home

然后我们就可以通过df -h 看到mount 的目录或者mount 来查看

如果需要开机启动时自动mount,我们需要编辑/etc/fstab

192.168.1.101:/home /home nfs rw,sync,hard,intr 0 0

移除NFS mount

umount /home

Online.net Xenserver 使用RPN-SAN的诸多问题

Online.net 的系统本身就有很多问题,加上XenServer 以后问题就更多了,再加上RPN – SAN 以后,那问题就更更更多了。。。

为什么要是用RPN-SAN? 

因为online.net 的服务器很多都是纯SSD 服务器,如果我们需要放置大量的图片的话,显然是不够的,这个时候RPN-SAN 就派上用场了, 在纯dedicated server上使用SAN,那是很容易的事情,直接挂载就可以了,在XenServer上挂载iSCSI 的 SAN,则稍微麻烦点, 有几点注意事项:

  1. XenServer 7 是建立在CentOS 7 上面的, iSCSI用的port 是3260, 所以需要在防火墙上打开3260
  2. Online.net 的RPN-SAN 用的是内网,位于 10.88.0.0/14. 如果你的online.net 的服务器是用的IPMI 安装的系统,那么你需要把这台服务器自带的Private IP 配置上. 关于private ip 的 netmask,和gateway 可以先用DHCP 激活,然后自己记录下来,稍后你可以一直使用DHCP,或者按照自己的意愿使用static
  3. 在购买完了Online.net 的 RPN-SAN以后,你需要在此RPN-SAN的管理页面,给使用此RPN-SAN 的dedicated server授权,这是从security 的角度考虑
  4. 于此同时,你还需要在RPN Group里面,把RPN-SAN 和使用此SAN 的服务器放置于同一个Group里面
  5. 一般来说,RPN-SAN 和 服务器的Private IP 需要在一个网段,我们这里可以使用10.88.0.0/14 或者10.90.0.0/15
  6. XenServer 需要手动添加一条面向private network 10.88.0.0/14 或者10.90.0.0/15的 route,这样是他们互相通信,为了方便,此文下面假设我们使用的是10.90.0.0/15这个网段
  7. XenServer 通过xapi 添加static route 的办法:
xe network-list
xe network-param-set uuid=<UUID> other-config:static-routes=10.90.0.0/15/10.90.23.1

在这命令里面,我们的网卡为xenbr2,IP 为10.90.23.44, Gateway 为10.90.23.1

运行完这条命令, 如果我们使用route -n 来查看route, 会发现没有任何变化, 这是因为我们需要重启系统或者运行xe-toolstack-restart 来使新的配置生效

添加static route 很简单,但是删除就比较麻烦了. 删除的话,需要一次性删除所有的static route,然后再添加我们认为必须的route.

删除所有static route:

xe network-param-remove uuid={network UUID} param-name=other-config param-key=static-routes

If there were some needed static route, add them back, for example:

xe network-param-set uuid={network UUID} other-config:static-routes=192.168.98.0/24/192.168.1.1,192.168.99.0/24/192.168.1.1

 

After that, reboot to make them take effect.

对于storage来说,我们经常会把NIC 的MTU 改为9000, steps to modify MTU in Senserver:

  1. shutdown guests
  2. reconfigure network

xe network-param-set uuid=<network-uuid> MTU=9000

      3. reboot hosts

       4. verify proper MTU sizing

俩教训。。。

最近一周有点郁闷,浪费了太多的时间

  1. 手上有两台朋友公司退下来的低配置的笔记本,跑windows有点问题,但是跑ubuntu来写代码没有任何问题. 于是按一贯的套路去安装virtualbox,vagrant, laravel。。。结果发现vagrant up 就是无法启动虚拟机,总是卡在ssh auth 这一步、、、结果debug了一个星期,才发现原来是CPU 不支持VT-X。。虽然主板支持,但是没有任何用。。nnd。。还是正常使用吧,别用什么虚拟机了
  2. 自己的几个websites 用的是piwik 来做visitor analyse, 但是其中一个站点我今天enable了 cloudflare SSL 就发现无法追踪visitor了。。。突然想起来莫非是没有装ssl 的piwik 无法记录有SSL 的website? 后来一看。。果然还真是这个问题。。。

 

哎,最近诸事不顺啊。。

使用自签发的SSL证书来加密nginx与后端服务器的通讯

这个问题很有意思,说起来还是由于可恶的GFW. 我目前使用一台阿里云华南的服务器来服务国内客户,然后用一台阿里云HKB 的服务器 + CDN 来服务国外客户. 但是郁闷的是,HKB 的服务器,nginx运行一会就回出现502 bad gateway,但是把HKB 的业务放在其他的服务商那里,就不会出现这个问题, 而且如果你不是用80端口,也不会出现这个问题

这个debug了将近一个星期才猛然间意识到,这也许是因为GFW 和阿里云盾的敏感词过滤系统,强制TCP 触发RST标志,造成502 connection reset

目前看来唯一的办法就是上https, 也就是说要secure data transfer between nginx and its upstream。。。我发现对我来说,还是英语描述比较完整

在这种情况下,nginx 的 upstream 要是用https, 但是因为只是作为内部数据传输,因此可以不用去买SSL证书,直接用self signed 的证书就可以了.

nginx 的官方,有一篇比较权威的教程:

https://www.nginx.com/resources/admin-guide/nginx-https-upstreams/

但是说实话,这个比较复杂,用的是SSL 的双面认证,类似于国内的网上银行的验证方式,而对于我们这种情况,只需要单向认证就可以了. 也就是说只需要在 后端的nginx 的服务器上安装自签发的SSL证书即可,前端nginx 配置调整为proxy_pass https.

关于如何给nginx安装自签发的ssl 证书,国内的教程也比较多,但是大部分都是先自建CA key crt,再签发,比较麻烦, 类似于这样:

http://blog.creke.net/762.html

这样做比较适合双向SSL认证

一个简单的方式可以借助下面的blog提到的方式:

http://blog.topspeedsnail.com/archives/3768

下面简单说下:

现在很多网站都使用https进行加密通讯及对网络服务器身份的鉴定。这遍文章介绍怎么在Nginx web服务上设置自签名SSL证书。由于不是由权威机构发布的证书,它(自签名证书)不能确认网络服务器身份,但是它可以对通信进行加密。

自签名证书适合个人或公司内部使用,如果要对外提供web服务,最好购买权威机构发布的证书。在github上有一个项目叫Let’s Encrypt,可以使用它签发免费的证书,并且大多数web浏览器都信任它。

创建SSL证书

我们可以创建一个目录用来存放所有SSL相关文件,在/etc/nginx下创建:

创建 SSL密钥和证书文件:

$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

我们来看一看上面命令各个选项的意思:

openssl:这是创建和管理OpenSSL密钥、证书和其它文件的命令行工具
req:指定使用X.509证书签名要求(CSR)
-x509:创建自签名证书,而不生成签名请求
-nodes:证书不使用密码,我们需要Nginx能直接读取文件,在重启Nginx时,不用输入密码
-days 365::证书的有效时间,这里是一年
-newkey rsa:2048:同时生成一个新证书和新密钥,RSA密钥长度:2048位
-keyout:密钥生成的路径
-out:证书生成的路径
执行上面命令,需要回答一系列问题。其中,最重要的一个问题是Common Name (e.g. server FQDN or YOUR name),输入你的域名。这里可以使用泛解析. 如果没有域名的话,使用ip地址。

这样就会生产key 和 crt

一个简单的nginx配置例子:

server {
 listen 80 default_server;
 listen [::]:80 default_server ipv6only=on;
 
 listen 443 ssl;
 
 root /usr/share/nginx/html;
 index index.html index.htm;
 
 server_name your_domain.com;
 ssl_certificate /etc/nginx/ssl/nginx.crt;
 ssl_certificate_key /etc/nginx/ssl/nginx.key;
 
 location / {
 try_files $uri $uri/ =404;
 }
}

discuz x3.2 启动SSL

这是一篇别的地方看到的文章,把所有需要修改的地方都说了,很有借鉴意义,这里就转载过来做个记录

————————————————————————————————————————————–

Discuz! X3.2 本身对 HTTPS 的支持很有限,程序本身支持,但还有很多地方需要调整和修改的。
站点全部链接默认 HTTPS ,无任何 HTTP 链接通过 301 跳转到 HTTPS 。 浏览器显示绿色安全标志,无“不安全内容”提示。

具体来说,我们需要从以下 6 个方面来实现我们最终的效果。

服务器前端程序的配置
一般来说,大家多使用 Nginx 作为前端程序,关于 Nginx 开启 HTTPS 的教程,网上有很多教程,可以参考这篇文章:

https://aotu.io/notes/2016/08/16/nginx-https/
Discuz 判断服务器是否使用 SSL 的修补和完善
 Discuz 判断服务器是否使用 SSL 的代码不适合 Nginx+CGI 的情况,即 PHP-FPM 。这个时候我们需要修改以下文件:
 Discuz 采用 $_SERVER[‘ HTTPS ’] 的方式来判断 SSL ,但是因为服务器 架构问题( nginx+php-fpm ),无法采用这种方式识别,所以需要对 Discuz 程序进行一些调整(使用 $_SERVER[‘ SERVER_PORT ’] 来判断)。 source/class/discuz/discuz_application.php (约第 187 行处): 查找:
 $_G['isHTTPS'] = ($_SERVER['HTTPS'] && strtolower($_SERVER['HTTPS']) != 'off') ? true : false;
 修改为:
 $_G['isHTTPS'] = ($_SERVER['SERVER_PORT'] == 443 || $_SERVER['HTTPS'] && strtolower($_SERVER['HTTPS']) != 'off') ? true : false;
uc_server/avatar.php (约第 13 行处):
 查找:
 define('UC_API', strtolower(($_SERVER['HTTPS'] == 'on' ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST'].substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/'))));
 修改为:
 define('UC_API', strtolower(($_SERVER['SERVER_PORT'] == 443

除去非 HTTPS 内容避免提示”不安全内容“
Source/plugin/manyou/Service/DiscuzTips.php ,最后的那段 JS 加载脚本删除就行。
非楼主层如果有点评,那么点评者头像不是 HTTPS 开头,也需要修改一个文件来适配: template/default/forum/viewthread_node_body.htm (约 180 行),搜索 div class=”psta vm”>,将下面一行注释掉或者删除。
打开浏览器,使用开发者工具或者查看源码逐一排查加载的非 HTTPS 资源并修改。

后台设置的修改完善
在后台还有一些设置,可能会干扰 https 的使用
后台 >全局 > 站点 URL ,改为 https 开头的
后台 > 站长 > UCenter 设置 > UCenter 访问地址,修改为 https 开头的
UCenter 后台 > 应用管理 > 应用的主 URL ,修改为 https 开头。修改后可能会显示通讯失败,如果 UC 和论坛程序安装在同一机器,此失败可无视,实测可以和 UC 正常通讯不影响(测试是否正常通讯程序的 Bug ),如果 UC 和论坛程序不在一台机器上,有可能不能通讯。 另外在 后台 > 全局 > 域名设置 中的一些设置也可能使 https 失效,如果更新缓存后论坛默认连接还是 HTTP ,请删除 后台 > 全局 > 域名设置 > 应用域名 > 默认 里面的默认域名(一般去 forum.php 尾巴这里会有内容,为了 HTTPS 请删除)。

模板的调整
主要在模板的 foot.html 以及 header.html 等文件中,使用工具逐一排查模板文件中写死的 HTTP 链接,修改为 HTTPS 。

数据库的调整
在论坛这种交互社区中,经常回复发帖时会有出现主域名的链接,在没有 HTTPS 之前,链接都是 HTTP 开头,这个时候,我们需要修改数据库,运行下面的 mysql 命令更新数据库,将 HTTP 替换为 HTTPS :
进入 DZ 后台:站长 – 数据库 – 升级

UPDATE pre_forum_post SET message=REPLACE(message,’http://www.repaik.com‘,’https://www.repaik.com‘);
请将 www.repaik.com 替换为自己的域名

需要注意的是,出于安全考虑, Discuz 后台默认情况下禁止 SQL 语句直接执行,只能使用常用 SQL 当中的内容,如果想自己随意书写 SQL 升级语句,需要将程序文件 config/config_global.php 当中的$_config[admincp][runquery] 设置修改为 1 。

nginx 隐藏版本version

现在我旗下的网站基本全部都转移到nginx了,但是nginx 出现40X 和 50x 的错误的时候,经常会显示版本号,这让我很不爽

无意间看到某个nginx站点出问题的时候,竟然不显示版本号。 google 了一下,原来nginx 有个命令叫做server_tokens, 把它设置为off 即可

 

Syntax: server_tokens on | off | build | string;
Default: 
server_tokens on;
Context: http, server, location