這個項目實現了:
a) 網站過濾:允許/不允許訪問某些網站;
b) 用戶過濾:支持/不支持某些用戶訪問外部網站;
c) 網站引導:將用戶對某個網站的訪問引導至一個模擬網站(釣
魚)。
d) 緩存功能:要求能緩存原服務器響應的對象,並能夠通過修改請求報文(添加 if-modified-since頭行),向原服務器確認緩存對象是否是最新版本
首先,先要把django包內的C:\Python27\Lib\site-packages\django\core\handlers\base.py 中的^$改為.* 。(共有兩處需要修改),以此來保證能讓所有的url目標都傳到views里面的函數中。
如圖
然后構建一個django項目,可以不帶有admin模塊,然后建立一個新的app
博主構建的項目結構如下,其中Cache.py是一會再創建的
下面是models.py的代碼
#coding=utf8
from django.db import models
class fish(models.Model):
#釣魚規則表
user_ip = models.CharField(max_length=15) #客戶ip
forbidden_host = models.CharField(max_length=100) #禁止的host
fish_url = models.CharField(max_length=100) #跳轉的網站鏈接
class firewall(models.Model):
#黑名單規則表
user_ip = models.CharField(max_length=15) #客戶ip
forbidden_host = models.CharField(max_length=100) #禁止的host
class cache(models.Model):
#緩存表
timestamp = models.CharField(max_length=80) #時間戳
name = models.CharField(max_length=150) #文件名對應的url
content_type = models.CharField(max_length=50) #內容類型
content = models.TextField() #內容
def check_if_replace(user_ip, host):
user_list = firewall.objects.filter(user_ip=user_ip).all() #先到黑名單中查找
for user in user_list:
if user.forbidden_host in host or host == '*':
return (1, '<h1>You have been forbidden!</h1>') #返回禁止頁
general = firewall.objects.filter(user_ip='*').all()
for i in general:
if i.forbidden_host in host:
return (1, '<h1>You have been forbidden!</h1>')
fish_list = fish.objects.filter(user_ip=user_ip).all() #然后到釣魚規則中查找
for fisher in fish_list:
if fisher.forbidden_host in host:
return (-1, fisher.fish_url)
return (0, host)
這一部分是用來做規則的存儲和緩存的存儲,migrate之后各表如下所示
這張表用來做禁止規則的配置,可以用'*'作為通配符,實現所有用戶對單一網站和對某用戶做屏蔽。
這張表用來做釣魚規則的配置,用戶轉到指定的目標
這張表作為緩存的實現
views.py的代碼:
#coding=utf8
import re
from contextlib import closing
from django.http import HttpResponse,HttpResponseRedirect
from Cache import *
def home(request):
url = request.path[1:].split('/')
url = url[0] + '//' + url[1] + '/'
url = request.path[1:].replace(':/', '://') #獲得目標url
host = request.get_host()
method = request.method
if request.META.has_key('HTTP_X_FORWARDED_FOR'):
ip = request.META['HTTP_X_FORWARDED_FOR'] #獲取客戶端ip
else:
ip = request.META['REMOTE_ADDR']
regex = re.compile('^HTTP_')
headers = dict((regex.sub('', header), value) for (header, value)
in request.META.items() if header.startswith('HTTP_'))
if len(request.REQUEST.items()) > 0:
url += '?'
for (i, j) in request.REQUEST.items():
url += str(i) + '=' + str(j) + '&'
url = url[:-1] #將帶參數的get請求恢復成原始鏈接狀態
check_tuple = check_if_replace(ip, host)
if check_tuple[0] == 1:
return HttpResponse(check_tuple[1]) #如果符合黑名單規則,返回禁止頁
elif check_tuple[0] == -1:
url = check_tuple[1]
return HttpResponseRedirect(url) #如果符合釣魚規則,那么重定向到指定的網站
cacher = Cache(url)
if cacher.check_cache(): #檢查是否有與目標網站一致的資源
res = cacher.get()
return HttpResponse(res[0], content_type=res[1]) #將緩存的內容返回
else:
with closing(requests.request(method, url, headers=headers, data=request.POST, stream=True)) as r:
cacher.update(bytes(r.content), content_type=r.headers['content-type']) #更新緩存
return HttpResponse(bytes(r.content), status=r.status_code, content_type=r.headers['content-type']) #返回資源
Cache.py的代碼
#coding=utf8
import requests
from models import *
import time
class Cache():
def __init__(self, url):
self.url = url
def check_cache(self):
'''
檢查是否有一致的緩存
:return: Boolean型
'''
try:
f = cache.objects.get(name=self.url)
headers = {'If-Modified-Since': f.timestamp}
if requests.get(self.url, headers=headers).status_code == 304:
return True
else:
return False
except:
return False
def update(self, content, content_type):
'''
更新緩存
:param content: 內容
:param content_type: 內容類型
:return:
'''
try:
f = cache.objects.get(name=self.url)
f.content = content
f.content_type = content_type
f.name = self.url
t = time.asctime().split()
f.timestamp = t[0] + ', '+t[2] + ' '+t[1] +' '+t[4]+' '+t[3] + 'GMT'
f.save()
except:
f = cache()
f.content = content
f.name = self.url
t = time.asctime().split()
f.timestamp = t[0] + ', ' + t[2] + ' ' + t[1] + ' ' + t[4] + ' ' + t[3] + ' GMT'
f.content_type = content_type
f.save()
def get(self):
#獲取緩存
f = cache.objects.get(name=self.url)
return (f.content, f.content_type)
最后修改urls.py
from django.conf.urls import include, url
# from django.contrib import admin
from server.views import *
urlpatterns = [
# url(r'^admin/', include(admin.site.urls)),
url('.*',home),
]
為了防止post的時候受干擾,把settings.py中的中間件去掉csrf,剩下的如圖
下面啟動項目,監聽8000端口
把瀏覽器設置代理為127.0.0.1:8000
打開博客園首頁,正常顯示
訪問人人網,由於黑名單的表中有這條規則,返回我們寫的禁止頁
訪問愛奇藝,由於釣魚規則中配置了將愛奇藝引導到博客園,返回的是對博客園的重定向
到此就完成了一個簡單的HTTP代理服務器