记一次搭建靶场遇到的各种问题以及解决方案-Alkaid

0x01 python服务器的选择问题

靶场用了flask框架,在选择服务器时,我搜到很多不懂的知识,于是做个总结,首先来看下面几个概念:

记一次搭建靶场遇到的各种问题以及解决方案-Alkaid

1.WSGI(规范)

Python Web Server Gateway Interface (或简称 WSGI,读作“wizgy”),WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web server如何与web application通信的规范。

WSGI允许开发者将选择web框架和web服务器分开。可以混合匹配web服务器和web框架,选择一个适合的配对。比如,可以在Gunicorn 或者 Nginx/uWSGI 或者 Waitress上运行 Django, Flask, 或 Pyramid。真正的混合匹配,得益于WSGI同时支持服务器和架构.

web服务器必须具备WSGI接口,所有的现代Python Web框架都已具备WSGI接口,它让你不对代码作修改就能使服务器和特点的web框架协同工作。

WSGI由web服务器支持,而web框架允许你选择适合自己的配对,但它同样对于服务器和框架开发者提供便利使他们可以专注于自己偏爱的领域和专长而不至于相互牵制。其他语言也有类似接口:java有Servlet API,Ruby 有 Rack。

2.uWSGI(服务器)和uwsgi(协议)和WSGI(协议)

uWSGI实现了WSGI的所有接口,是一个快速、自我修复、开发人员和系统管理员友好的服务器。uWSGI代码完全用C编写,效率高、性能稳定。

uwsgi是一种线路协议而不是通信协议,在此常用于在uWSGI服务器与其他网络服务器的数据通信。uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型。

WSGI协议其实是定义了一种server与application解耦的规范,即可以有多个实现WSGI server的服务器,也可以有多个实现WSGI application的框架,那么就可以选择任意的server和application组合实现自己的web应用。例如uWSGI和Gunicorn都是实现了WSGI server协议的服务器,Django,Flask是实现了WSGI application协议的web框架,可以根据项目实际情况搭配使用。

记一次搭建靶场遇到的各种问题以及解决方案-Alkaid

3.Gunicorn(服务器)

Gunicorn是一个被广泛使用的高性能的Python WSGI UNIX HTTP服务器,移植自Ruby的独角兽(Unicorn )项目,使用pre-fork worker模式,具有使用非常简单,轻量级的资源消耗,以及高性能等特点。

Gunicorn 服务器作为wsgi app的容器,能够与各种Web框架兼容(flask,django等),得益于gevent等技术,使用Gunicorn能够在基本不改变wsgi app代码的前提下,大幅度提高wsgi app的性能。

4.Tornado(服务器+框架)

tornado是一个轻量级的web框架,是一个用python写的web服务器,它有三个最大的特点(优势)速度、简单和可扩展性。

编写tornado应用做多最多的工作就是定义一个类去继承tornado中的RequestHandler

5.Nginx

Nginx是一个Http和反向代理服务器
什么是反向代理服务器呢?

正向的就是由浏览器主动的想代理服务器发出请求,经代理服务器做出处理后再转给目标服务器
反向的就是不管浏览器同不同意,请求都会经过代理服务器处理再发给目标服务器

这其中的区别就是必须经过Nginx反向代理服务器,这就有了使用Nginx的几个好处:

(1)安全:不管什么请求都要经过代理服务器,这样就避免了外部程序直接攻击web服务器
(2)负载均衡:根据请求情况和服务器负载情况,将请求分配给不同的web服务器,保证服务器性能
(3)提高web服务器的IO性能:这个我也没看懂,总结来说就是请求从客户端传到web服务器是需要时间的,传递多长时间就会让这个进程阻塞多长时间,而通过反向代理,就可以在反向代理这完整接受请求,然后再传给web服务器,从而保证服务器性能,而且有的一些简单的事情(比如静态文件)可以直接由反向代理处理,不经过web服务器

记一次搭建靶场遇到的各种问题以及解决方案-Alkaid

0x02 服务器搭建以及Nginx反向代理

由于简单方便,所以我最后使用了gunicorn+Nginx反向代理的方式,写下过程:

安装Gunicorn(使用了python3,所以用了pip3安装,没能解决python2,3的gunicorn共存的问题)

pip install gunicorn

启动Gunicorn

gunicorn [options] module_name:variable_name

module_name对应python文件,variable_name对应web应用实例。

例如:

gunicorn -w 3 -b 127.0.0.1:8000 main:app

在8000端口上开启3线程,运行main.py

  • -w 4是指预定义的工作进程数为4,
  • -b 127.0.0.1:4000指绑定地址和端口
  • main是flask的启动python文件,app则是flask应用程序实例

安装Nginx

sudo apt-get install nginx

启动Ngnix

sudo /etc/init.d/nginx start

修改配置文件

cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak

修改为
server {
listen 80;

location / {
proxy_pass http://127.0.0.1:8000;
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 X-Forwarded-Proto $scheme;
}

这里将Nginx设置为代理模式,代理到本地的8000端口,之后就可以通过公网访问flask应用了

最后,总结下这几个部分的关系:

记一次搭建靶场遇到的各种问题以及解决方案-Alkaid
(nginx收到客户端发来的请求,根据nginx中配置的路由,将其转发给WSGI)
nginx:”WSGI,找你的来了!”
(WSGI服务器根据WSGI协议解析请求,配置好环境变量,调用start_response方法呼叫flask框架)
WSGI服务器:”flask,快来接客,客户资料我都给你准备好了!”
(flask根据env环境变量,请求参数和路径找到对应处理函数,生成html)
flask:”!@#$%^……WSGI,html文档弄好了,拿去吧。”
(WSGI拿到html,再组装根据env变量组装成一个http响应,发送给nginx)
WSGI服务器:”nginx,刚才谁找我来着?回他个话,!@#$%^…..”
(nginx再将响应发送给客户端)

0x03开机自启动

这个应该是最坑的地方了,因为是靶场所以我选择了ubuntu用户而不是root用户来启动flask,但是要想设置为开机自启,只能写到/etc/rc.local或者开机自启脚本里,但是如果这样做,默认就是root权限,所以从网上找到了supervisor这个工具来实现我的目的。

supervisor 从安装到使用

supervisor支持python2,python3上的我没做试验,这也是一个坑

(1)安装supervisor

pip2 install supervisor

(2)配置supervisor

生成配置文件:
echo_supervisord_conf > /etc/supervisor第二种方法是直接修改,/etc/sudoers

修改sudoes文件也有两种形式,

其一是给单个用户添加sudo权限。方法是

将这一行天追加udoers文件中:username ALL=(ALL:ALL) ALL

者方式取消用户的sudo权限,就是删除改行。d.conf

启动:
supervisord -c /etc/supervisord.conf

修改设置:
vim /etc/supervisord.conf
在配置文件底部,配置include

[include]
files=/etc/supervisor/*.conf #若你本地无/etc/supervisor目录,请自建

用supervisor管理进程,配置如下:

cd /etc/supervisor
vim flask.conf # 这里的文件名称自定义

加入以下内容:

这里是启动要配置的参数,请根据自己的项目自定义添加

更改了supervisor配置文件,需要重启,运行以下指令:

supervisorctl reload

(3)supervisorctl的用法

supervisord : 启动supervisor
supervisorctl reload :修改完配置文件后重新启动supervisor
supervisorctl status :查看supervisor监管的进程状态
supervisorctl start 进程名 :启动XXX进程
supervisorctl stop 进程名 :停止XXX进程
supervisorctl stop all:停止全部进程,注:start、restart、stop都不会载入最新的配置文件。
supervisorctl update:根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启

(4)supervisor开机自启动方法:

将上述脚本内容保存到/etc/rc.d/init.d/supervisor文件中,修改文件权限为755,并设置开机启动

注意:修改脚本中supervisor配置文件路径为你的supervisor的配置文件路径

或者使用省事的办法:

ubuntu下编辑/etc/rc.local文件:

vi /etc/rc.local

在exit 0 之前加入以下命令

/usr/local/bin/supervisord

保存并退出。
最后修改rc.local权限,重启试验效果

 

0x04 将ubuntu取消sudo权限

直接修改/etc/sudoers文件

直接删除该行或者注释掉