Nginx配置禁止IP直接HTTP/HTTPS访问

这样配置可以禁止IP直接HTTP/HTTPS访问,也使未绑定的域名无法访问。

#http
server 
{
  listen 80 default_server;
  server_name _;
  return 500;
}

#https
server 
{
  listen 443 ssl default_server;
  server_name _;
  ssl_certificate      /yourpath/ssl.crt;
  ssl_certificate_key  /yourpath/ssl.key;
  return 500;
}

需要配置秘钥 否则会到时全部ssl配置失效 不知道为啥

yum install -y openssl
openssl genrsa -des3 -passout pass:x -out ssl.pass.key 2048
openssl rsa -passin pass:x -in ssl.pass.key -out ssl.key
openssl req -new -key ssl.key -out ssl.csr
…… 一路回车 ……
openssl x509 -req -days 3650 -in ssl.csr -signkey ssl.key -out ssl.crt

Openresty最佳案例 | 第5篇:http和C_json模块

http客户端

Openresty没有提供默认的Http客户端,需要下载第三方的http客户端。

下载lua-resty-http到lualib目录下,使用以下的命令下载:

cd /usr/example/lualib/resty/  
wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http_headers.lua  

wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http.lua  

lua-resty-http模块的地址为https://github.com/pintsized/lua-resty-http

安装成功后,通过require(“resty.http”)引入 lua_http模块,它有以下的api方法:

  • syntax: httpc = http.new() 创建一个 http对象
  • syntax: res, err = httpc:request_uri(uri, params)根据参数获取内容,包括:
    • status 状态码
    • headers 响应头
    • body 响应体

vim /usr/example/lua/test_http.lua,写以下代码:

local http = require("resty.http")  

local httpc = http.new()  

local resp, err = httpc:request_uri("http://s.taobao.com", {  
    method = "GET",  
    path = "/search?q=hello",  
    headers = {  
        ["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36"  
    }  
})  

if not resp then  
    ngx.say("request error :", err)  
    return  
end  


ngx.status = resp.status  


for k, v in pairs(resp.headers) do  
    if k ~= "Transfer-Encoding" and k ~= "Connection" then  
        ngx.header[k] = v  
    end  
end  

ngx.say(resp.body)  

httpc:close()  

vim /usr/example/example.conf 加上以下的配置:

 location /lua_http {
   default_type 'text/html';
   lua_code_cache on;
   content_by_lua_file /usr/example/lua/test_http.lua;
 }

在Nginx的配置文件nginx.conf的http部分,加上以下dns解析:

vim /usr/servers/nginx/conf/nginx.conf
resolver 8.8.8.8;  

浏览器访问:http://116.196.177.123/lua_http,浏览器会显示淘宝的搜索页。

lua_cjson模块

Json是一种常见的数据交换格式,常用于http通信协议和其他数据传输领域。在openresty默认内嵌了lua_cjson模块,用来序列化数据。

lua_cjson模块的地址:https://www.kyne.com.au/~mark/software/lua-cjson-manual.html

它常用的API如下:

  • local cjson = require “cjson” 获取一个cjson对象
  • local str = cjson.encode(obj) obj转换成string
  • local obj = cjson.decode(str) 将string转obj

vim /usr/example/lua/test_cjson.lua,添加以下内容:

local cjson = require("cjson")  


local obj = {  
    id = 1,  
    name = "zhangsan",  
    age = nil,  
    is_male = false,  
    hobby = {"film", "music", "read"}  
}  

local str = cjson.encode(obj)  
ngx.say(str, "<br/>")  


str = '{"hobby":["film","music","read"],"is_male":false,"name":"zhangsan","id":1,"age":null}'  
local obj = cjson.decode(str)  

ngx.say(obj.age, "<br/>")  
ngx.say(obj.age == nil, "<br/>")  
ngx.say(obj.age == cjson.null, "<br/>")  
ngx.say(obj.hobby[1], "<br/>")  

vim /usr/example/example.conf添加以下内容:

 location ~ /lua_cjson {  
   default_type 'text/html';  
   lua_code_cache on;  
   content_by_lua_file /usr/example/lua/test_cjson.lua;  
 }   

在浏览器上访问http://116.196.177.123/lua_cjson,浏览器显示以下内容:

{"hobby":["film","music","read"],"is_male":false,"name":"zhangsan","id":1}
null
false
true
film

nginx访问日志GET后面用http://开头

今天检查nginx访问日志的时候发现奇怪的日志

[02/Nov/2017:13:35:46 +0800] "GET http://www.baidu.com/ HTTP/1.1" 200 8672 "http://www.baidu.com" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0" -

截图如下

未分类

这里取的只是百度的域名,还有好多其他的域名,这个应该是代理攻击

有没有发现GET后面用http://开头的,正常情况GET后面是用”/”开头,如下面的访问日志

[08/Nov/2017:21:54:15 +0800] "GET /2330.html HTTP/1.1" 200 8419 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36" -

这个问题在百度gogole的相关文章比较少,所以现在不清楚目前的处理方法是否正确,如果你要遇到了这个问题,可以尝试一下

目前处理的方法

#nginx中添加下面的配置,主要作用就是没有指定域名的返回444

server {
    server_name _;
    location / { 
        return 444; 
    }
}
server
{

    listen 443 ssl http2;
    server_name www.phpsong.com;
    //...


    #添加代码,主要作用如果域名不是www.phpsong.com的就返回444
    if ($host !~ ^(phpsong.com|www.phpsong.com)$) {
              return 444;
    }

    //...
}

设置之后,发现这种日志不存在了,因为不清楚模拟这种攻击,所以不清楚是否已经解决了,apache的解决方法可以看一下这个文章https://wiki.apache.org/httpd/ProxyAbuse

Nginx作HTTP的负载均衡max_fails和fail_timeout如何设置?

很多同学,经常利用Nginx来作HTTP的负载均衡,但是对于Nginx的负载均衡原理却了解得不够,如,今天讲解的max_fails、fail_timeout参数。

一、描述

在Nginx的负载均衡检查模块中,对于负载均衡的节点可以配置如下可选参数参数:

max_fails=1 fail_timeout=10s

这个是Nginx在负载均衡功能中,用于判断后端节点状态,所用到两个参数。

Nginx基于连接探测,如果发现后端异常,在单位周期为fail_timeout设置的时间,中达到max_fails次数,这个周期次数内,如果后端同一个节点不可用,那么接将把节点标记为不可用,并等待下一个周期(同样时常为fail_timeout)再一次去请求,判断是否连接是否成功。

默认:fail_timeout为10s,max_fails为1次。

二、探讨

经过这几天的压力测试和研究,如下:

1、在后端服务能力正常,nginx 可以调节如下阀值,增加其并发能力。

这些参数主要是一次请求,超时时间间隔。课程中有介绍到。

client_header_timeout 30;
client_body_timeout 30;
send_timeout 30;
read_timeout 30;```

这里,表示允许后端节点失败次数,如果调大,Nginx相当于把请求缓冲,如果整体的的后端服务处于可用状态,对于高并发的场景来说,建议适当调大是有效的。

max_fails=10 fail_timeout=60s`

当然,和所有优化阀值一样,数值加大,对应于给Nginx的压力也会相应加大。

2、检测方式及对后端服务性能

Nginx只有当有访问时后,才发起对后端节点探测。如果本次请求中,节点正好出现故障,Nginx将把请求转交给接下来的节点处理。所以不会影响到这次请求的正常进行。

利用Ansible部署运行Apache(http)的Docker容器

在自动化运维领域,除了saltstack,还有ansible这个批量安装部署工具,在写具体内容先,先谈谈我用过两个工具后的感想。

saltstack是C/S框架,要在客户端装软件,并且启动服务才能进行管理,ansible是通过ssh连接到客户端的,也就是说必须把密钥传给客户端才能进行管理,虽然可以关闭这个验证方式,但是生产环境中肯定是不能关闭的,从这一点看,还是ansible更容易配置,完全可以用脚本循环遍历所有主机来添加密钥。

使用方面,命令复杂程度相似,理解起来更容易的应该是saltstack,命令基本都是英语的组合,ansible则是依靠各种模式,参数来执行管理。

脚本编程方面,编程复杂度方面不尽相同,ansible提供群组的方式来对多主机提供管理,在推送操作到客户端时需给出明确的执行文件(yml),对于文件的存放位置没有明确的规定,saltstack需要在命令行提供主机信息,在推送时执行的是配置文件中提供的目录中的文件(sls),推送的文件也必须在这个目录中。

以上是我个人的一些见解,下面开始实战操作

环境介绍:

  • Centos 6.5
  • Ansible 2.3.0
  • Docker 1.7.1
  • Http 2.4.6-67

一、Docker操作

1. docker安装

这部分略过,如果你对docker安装和一些常用命令不了解,请参考《Docker常用命令和操作》

2. 拉取ansible镜像

docker pull ansible/centos7-ansible    #推荐使用这个镜像

拉取成功后可以在images里查看到这个镜像

未分类

3. 运行镜像,打开一个容器

docker run -it --name ansible 6883

4. 修改配置文件

vi /etc/ansible/hosts
[local]nlocalhostn  >>>>>  
[local]
localhost

这两个回车符在运行时是不能转义的,会报错

5. 提交修改后的容器

docker commit 1277 ansiblev2

6. 编写镜像构建方法

vim Dockerfile
FROM ansiblev2
MAINTAINER bin [email protected]


WORKDIR /opt/ansible    #定义工作区
RUN mkdir /opt/ansible/files    #创建必须目录
RUN mkdir /opt/ansible/template

ADD httpd.conf /opt/ansible/files    #把需要的文件复制到指定位置
ADD index.html.j2 /opt/ansible/template    
ADD web.yml /opt/ansible/

RUN ansible-playbook /opt/ansible/web.yml -c local  #运行ansible进行自动部署

VOLUME /var/www/html    #定义数据卷

CMD ["/usr/sbin/httpd","-X"]    #让httpd服务在前台运行
EXPOSE 80        #开放80端口,httpd.conf配置文件中必须也是80端口

二、Ansible操作

1. 编写服务部署方法

vim web.yml #ansible和saltstack在文字格式方面要求同样严格,如果报错,请查看格式是否正确!

- name: Configure webserver with http        #在运行时的提示信息
  hosts: local        #对本地主机组进行操作
  sudo: True        #运行时切换用户
  tasks:            #建立任务
    - name: install http
      yum: name=httpd update_cache=yes    #安装httpd,更新缓存
    - name: copy http config file
      copy: src=files/httpd.conf dest=/etc/httpd/conf    #文件复制

    - name: enable configuration
      file: >        #竖版写法,建立软连接
         dest=/etc/httpd/configure
         src=/etc/httpd/conf/
         state=link

    - name: copy index.html    #拷贝主页文件
      template: src=template/index.html.j2 dest=/var/www/html/index.html mode=0644

2. index.html.j2的内容

<html>
  <head>
    <title>Welcome to ansible!</title>
  </head>
  <body>
  <h1>http,configured by Ansible</h1>
  <p>If you can see this,Ansible successfully installed http.</p>
  <p>{{ ansible_env }}</p>    #会显示容器的环境变量
  #要想显示更多信息,可以通过ansible hostname -m setup来查看可以引用的变量
  <p>{{ ansible_env.PATH }}</p>    #显示环境变量中的PATH的值
  </body>
</html>

三、构建镜像,启动容器

1. 构建镜像

当前目录结构

未分类

docker build -t ansible/httpd .

2. 启动容器

docker run -d -p 8000:80 --name httpd ansible/httpd  #把容器的80端口映射到本地的8000端口

3. 查看容器运行情况

docker ps -a

未分类

4. 因为在构建镜像的时候指定了数据卷,可以在启动容器的时候挂载数据卷,方便代码修改

docker run -d -p 8001:80 -v /var/www/html:/var/www/html --name http2 ansible/httpd

四、测试主页

http://192.168.6.10:8000

未分类

出现如上显示为部署正常。

WireShark学习之抓取和分析HTTP数据包

1. 设置过滤条件

指定网络协议http

未分类

2. 打开Chrome浏览器输入网址

在浏览器输入https://sspai.com/post/30292

未分类

3. 在抓获得包中得到两个数据包,分别是HTTP请求以及HTTP响应

未分类

4. 双击打开 GET /30292 HTTP/1.1

未分类

5. 对Http协议包进行分析

HTTP请求消息头

  • Accept:call服务器,可以接收文件、网页和图片。
  • Accept-Charset:所接收的字符编码。
  • Accept-Encoding:可接收()压缩后的数据。
  • Accept-Language:Browser支持中、英文。
  • Host:要找的主机是。
  • If-Modified-Since:告诉服务器我们的缓冲中有这个资源文件,该文件的时间是,,
  • Referer:告诉服务器,我来自哪里。
  • User-Agent:告诉服务器,Browser内核。
  • Cookie:
  • Connection:保持连续发完信息后,我不关闭连接。
  • Date:Browser发送时间。

未分类

6. 查看Tcp流-Follow TCP Stream

未分类

未分类

7. 分析三次握手

三次握手的原理

在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

下图转自百度百科:

未分类

  • Wireshark中三次握手的具体情形

未分类

8. 总结

这些操作分为两步,第一步设置合理的过滤条件,第二步在任意数据包中选择Follow TCP Stream 。

Centos 7搭建、配置和使用Http代理(Squid服务器)

一、前言

最近搞了一台腾讯云内网服务器(把公网带宽调到了0Mbps),为了使内网服务器也能连上外网,稍微折腾了一下下Http代理。

本文以Squid代理服务器为栗子,简单介绍一下基本用法

二、安装Squid服务器

首先,在一台能同时连接公网和内网服务器的服务器上安装Squid代理服务器

yum install squid -y

然后就安装完了,是不是很简单呢(鬼才懒得编译呢)

三、配置Squid服务器

主要需要配置的是三个部分:

1、配置允许使用代理的IP地址

#此处使用10.0.0.0/16代表的是,整个10.0.x.x IP段都能使用(x代表任意255内的数字)
acl localnet src 10.0.0.0/16

#如果是限定单个IP使用,则是10.0.0.1/32
acl localnet src 10.0.0.1/32

2、配置允许访问的IP列表

第一个步骤是将10.0.0.0/16整个IP段命名标记为localnet,现在要将localnet添加进允许使用的列表中

#此处代表允许访问的列表包括localhost、manager、localnet三个IP段
http_access allow localhost manager localnet

3、配置Squid监听地址

这个步骤是为了进一步加强安全措施,防止代理服务器被滥用(盗用)

#最简便的规则,监听所有IP的3128端口,不安全,不建议使用
http_port 0.0.0.0:3128

#仅监听内网IP的3128端口,相对安全,建议使用
http_port 10.0.0.1:3128

四、使用代理

1、yum代理

#编辑/etc/yum.conf文件
vim /etc/yum.conf

#查找并修改或追加以下语句(将10.0.0.1修改为你的Squid配置的监听地址或服务器的IP):

proxy=http://10.0.0.1:3128/ 

2、wget代理

#编辑/etc/wgetrc文件
vim /etc/wgetrc

#查找并修改或追加以下语句(将10.0.0.1修改为你的Squid配置的监听地址或服务器的IP):

http_proxy=http://10.0.0.1:3128/
ftp_proxy=http://10.0.0.1:3128/

3、环境变量

#编辑/etc/profile文件
vim /etc/profile

#查找并修改或追加以下语句(将10.0.0.1修改为你的Squid配置的监听地址或服务器的IP):

http_proxy=http://10.0.0.1:3128/
ftp_proxy=http://10.0.0.1:3128/

export http_proxy
export ftp_proxy

http的变迁(http1.0-http2.0,https)

先来一张图来解释。。。

未分类

太模糊了?不急不急,让我们分步分析。

http1.0

http1.0早在1996年就出现了。基本上满足了ajax的需求,但是呢,毕竟刚出来没多久,在优化上就得多下功夫,在http开始普及之后,他的缺点也开始展现。

http1.0最大的问题就是关于tcp连接的问题,大家都知道tcp是连接型的协议,所以需要建立连接和断开连接。但是早期的http1.0只能在一个tcp上承载一个http,而且web端只能有6-8个链接,这就使高并发的状态下带宽利用率非常低。所以在99年,推出了http1.1。

http1.0与http1.1

下图表示了其主要区别

未分类

来详细说一说。

  • 缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。在这之中Etag也是最为重要的。它提供了精确的缓存定向。可以精确缓存某个文件而不是根据日期全部缓存。浏览器缓存控制

  • 带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。

  • 错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。

  • Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。Host,referer,origin三者区别

  • 长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

好了,现在已经优化到http1.1了。但是是不是还有问题呢。有肯定是有的,在这之前我们先说一下https;

http与https

https其实和http差不多,就是加了个s嘛,实质上也是,https是http上加了一层安全套接层(SSL :safe socket level),也就是这样。

未分类

http1.1与SPDY

然而http1.1还有几个明显的缺点,
一是会发生堵塞:请求到达的服务器的速度是不同的,如果先发的请求先到达可能会发生阻塞,这样带宽就降低了
二是不支持服务端推送,如果要求做一个服务端数据变动页面立即改变的组件就很难做。要用短轮询和长轮询。这样对带宽影响也是很大的。

所以,GOOGLE推出了SPDY。

未分类

SPDY是基于https的,也就是这样。

未分类

嘛,SPDY解决的问题还是很多的。具体如下。

  • 降低延迟,针对HTTP高延迟的问题,SPDY优雅的采取了多路复用(multiplexing)。多路复用通过多个请求stream共享一个tcp连接的方式,解决了HOL blocking的问题,降低了延迟同时提高了带宽的利用率。

  • 请求优先级(request prioritization)。多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY允许给每个request设置优先级,这样重要的请求就会优先得到响应。比如浏览器加载首页,首页的html内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。

  • header压缩。前面提到HTTP1.x的header很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量。

  • 基于HTTPS的加密协议传输,大大提高了传输数据的可靠性。

  • 服务端推送(server push),采用了SPDY的网页,例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。SPDY构成图:

SPDY与http2

结果httpSPDY这么好用,基本上大家都在用,就基于SPDY推出了 http2.0,而且把SPDY的优势用在了http上,也就是可以不用加密也能使用。而且稍微的把头部压缩算法换了一换。

具体来说

  • HTTP2.0 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS
  • HTTP2.0 消息头的压缩算法采用 HPACK http://http2.github.io/http2-spec/compression.html,而非 SPDY 采用的 DEFLATE http://zh.wikipedia.org/wiki/DEFLATE

综合上文 来个完整的流程图吧。

未分类