使用python完成对https请求的响应及一些安全策略
Web主机配置
- 阿里云1核2G,1Mbps带宽,CentOS 8.2 64位
- Apache Web服务器
- 暂时还未完成域名备案以及SSL证书安装
起源
最近和同学合作一款微信小程序,他负责前端,我负责后端。由于python比较容易上手,所以选择python编写后端程序。
后端完成的功能:
- 完成对前端请求的响应
- 防止数据泄露
我接触后端只有几天,所以可能里面内容都是基础或是基础也算不上。有什么不足和可以改进之处希望可以指出。也希望大神们不要攻击我的服务器。
安装Web服务器
我使用的Web服务器为Apache,目前也有很多Nginx。Nginx在网站流量较高的场合更有优势,而在我主机带宽只有1Mbps下,两者似乎差不大多。
yum install -y httpd #安装apache
systemctl start httpd #启动apache
chkconfig httpd on #apache开机自启动
开启端口
首先在阿里云控制台中配置安全组规则,开放你想要打开的端口。
安全组在控制台左侧菜单->网络与安全->安全组,点进去,配置规则,开放你想要开放的端口。
如果你设置了firewall或者iptables,同样也要在其中开放这个端口,或者直接关闭firewall和iptables。这里以打开80端口为例,列出了你可能需要用到的指令。
#关闭firewall
service firewalld stop
#firewall开放80端口
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload #重新载入防火墙设置
#关闭iptables
service iptables stop
#iptable开放80端口
vim /etc/sysconfig/iptables #打开iptables配置文件,在其中添加下面这行
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
service iptables restart #重启iptables
#或
iptables -I INPUT -p tcp --dport 80 -j ACCEPT #开放80端口,单单使用这句也可以开放,但是重启iptables后失效
service iptables save #将上一条语句写入/etc/sysconfig/iptables中
到此,你的服务器就可以对http请求进行响应了。在/var/www/html/目录下放入随便从哪找来的index.html,再在你电脑的浏览器中输入Web主机的公网ip,浏览器中便能显示刚刚放在Web主机上的网页了。
编写Python程序
首先我们需要进入到/var/www/html/目录下,启动Apache后,该目录将会对外公开。在这里我们需要创建一个python文件,用于实现后端功能。
cd /var/www/html/
mkdir port90 #创建一个目录,避免和主页文件混在一起
cd port90
vim port90.py #创建py文件
在py文件中写入以下内容:
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
class Resquest(BaseHTTPRequestHandler):
def handler(self):
print("data:", self.rfile.readline().decode())
self.wfile.write(self.rfile.readline())
def do_GET(self):
if self.path != '/':
self.send_error(404,'Page Not Find')
return
print('\n'+self.command)
print(self.client_address)
print(self.requestline)
req_datas = self.rfile.read(int(self.headers['content-length'])).decode()
print(req_datas)
data = {
'code': '200',
'message': 'Success',
'explain': ''
}
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(data).encode())
if __name__ == '__main__':
host = ('', 90)
server = HTTPServer(host, Resquest)
print("Starting server, listen at: %s:%s" % host)
server.serve_forever()
到此,你的服务器就可以根据你的需求对http请求进行相应了。do_GET是对http的GET请求进行处理,其他还有POST请求,PUT请求,DELETE请求等等,对应的函数都是同样的命名方式。
由于我们使用了另一个端口,因此我们需要重复上一步的操作,再打开一个端口。
本地请求
为了方便后续调试,建议在本地写一个python程序用于发起请求。程序如下:
import http.client
import json
ip_port = '' #这里换成自己服务器的域名:port或者ip:port
conn = http.client.HTTPConnection(ip_port)
data = 'test'
headers = {"Content-type":"text/html;charset=UTF-8"}
conn.request('GET', '/', data ,headers)
response = conn.getresponse()
content = response.read().decode()
print(content)
此程序的作用是向服务器分别发起一次GET请求,并打印出响应。服务器端运行python程序,本地再运行python程序便能查看结果。
让程序与窗口分离
虽然现在可以正常请求与响应,但是你会发现当你关闭终端时,python程序不再运行了,也就是说,你必须让你的电脑与Web主机保持连接,否则python程序将会终止,服务器不再可以根据你的想法对http进行响应。
这里我们可以使用tmux,将会话与窗口分离,实现终端窗口关闭而程序仍在会话中继续运行。
sudo yum install tmux #安装tmux
tmux new -s 'port90' #创建名为port90的会话
python3 port90.py #运行程序
#此时按Ctrl+b,松开后按d可分离会话
现在你就可以关闭ssh连接,本地运行刚刚的python程序,可以正常获取服务器的响应。
API规范化
我的主要任务是提供API给前端,让前端可以通过API调用Web主机的资源。响应内容格式的规范化有助于前端调试时更快找到错误原因。一般情况下响应分为这么几个部分:响应行、响应头、响应体。具体可以看这个博客。
API的规范化可以参考这篇文章。
安全策略
目前服务器尚未投入使用,但是我发现总有很多访问记录,我担心数据泄露以及服务器安全,故增加一些安全措施,尽可能避免这些问题。
-
设置ip黑名单,
若一个ip出现异常访问,可能是爬虫也可能是攻击者,不论怎样,列入黑名单,同时使用iptables屏蔽该ip。
iptables -I INPUT -s 123.44.55.66 -j DROP #封杀123.44.55.66 iptables -D INPUT -s 123.44.55.66 -j DROP #解除封杀123.44.55.66 service iptables save #将上一条语句写入/etc/sysconfig/iptables中
-
检查访问路径
访问我服务器的大多是一些爬虫,它们只会访问固定的几个路径,我们只需判断其访问路径是否合法,不合法则直接发送404响应即可。
-
限制访问次数
记录一个ip在同一天内访问的次数,大于次数则直接发送错误响应。
-
限制请求的字符串长度
由于我在程序中使用了eval()函数,因此很怕传入的字符串中出现一些python语句,故限制字符串长度。
-
关键字检查
理由同上,这里主要检查如os,import等关键词,出现则返回错误响应。
-
数据中加入token
关于token可以参考这个博客
-
数据传输加密
数据传输加密方式有很多种,我使用的就不公开了。可以参考这个博客。