拦截请求_技术分享 | 拦截内网 HTTP 请求方法

概述

运维管理过程中,有时需要对网络中访问站点做限制,比如禁止访问某个网站。接下来给大家介绍一种方法 :拦截 HTTP 访问请求。本文以 http://www.demo.com 为例进行说明。

环境依赖

为了拦截 HTTP 请求,我们需要在网关处抓取数据包,并且发送我们自己的包给用户。这里我们使用 scapy,这是一个 Python 包,用来抓取和构造数据包很方便。在装 scapy 之前需要先安装 libpcap,之后即可使用如下命令安装:

# pip install scapy

通信过程分析

对于 TCP 通信,最基本的便是三次握手。为了拦截用户的 HTTP 请求,我们需要详细了解一下 HTTP 的通信过程,如图 1 为一次完整的 HTTP 请求:

bcdf35896ffcd57bcc22447f1cf3b3d8.png

图 1:HTTP通信过程

从图 1 可看出前 3 个包为三次握手过程,第 4 个包为客户端发往服务端的请求。详细构成如图 2 所示:

ec4c726f4220de4b546b61a8cac0f413.png

图 2:HTTP请求

紧接着服务端发送了 5、6 两个包。从图 2 和图 3 红色框标记的地方可知,其中第 5 个包是服务端对客户端发送的第 4 个包的应答。

69640b67189b18b47796aa6ca772240f.png

图3:服务端应答报文

第 6 个包为服务端对客户端 HTTP 请求的应答。详细构成如图 4 所示:

1d3a830f48074b468ed9bd7e3b67bfd0.png

图4:HTTP应答报文

接着第 7 个包是客户端对第 6 个包的应答报文,最后第 8-10 个包为四次挥手过程,断开连接。

拦截实现

通过上面对 HTTP 通信过程的分析,不难发现为了拦截用户特定的 HTTP 请求,需要从第 5 和第 6 个包入手。

判断一个包是否为 HTTP 请求报文

首先我们需要判断抓到的包是否为 HTTP 请求报文,因为 HTTP 报文是通过明文传输的,如图5所示。一个简单的方法是判断数据包中是否存在\r\nHost: www.demo.com\r\n 即可。

c24076545cbfe7bf0691764b59dcc5e9.png

图 5:HTTP报文明文

构造自己的数据包

当收到一个数据包匹配到了我们指定的域名时,我们需要构建自己的数据包发给用户。通过上面的分析,我们至少需要构造 2 个包,图 1 中的第 5 和第 6 个包。另外,还有两点需要注意,其一:因为 HTTP 请求还是会到达服务端的,为了阻止服务端继续返回数据,我们需要再构造一个 RST 报文,断开该 TCP 连接。其二:为了阻止用户继续访问该域名,我们同样需要构造一个发往客户端的 RST 报文。最终结果如图 6 所示。

ea4f453598bffbb40cdff9f12846b8d2.png

图 6:拦截结果

下面对图六中部分数据包说明:

第 5-6 个 RST 包对应第 3 个包,第 7-9 个 RST 包对应第 4 个包,为了防止丢失,我们多发了几次。

第 10 和第 15 个包是我们构造的对应第 4 个包的 HTTP 请求的应答(发送了两次)。

第 11 个包是客户端对第 10 个包的应答。

第 12 和第 14 个包是我们构造的发给客户端的RST报文。

第 13 个包则是服务端发送的FIN报文。

第 16-19 个包则是客户端和服务端产生的额外控制报文。

运行结果

图7是在我们没有拦截的情况下返回的输出,为 WWW.DEMO.COM ,图 8 是在拦截的情况下的输出,为 HELLO WORLD

38c3b18e7962e21c425e800e4e424ce7.png

图 7:正常情况下输出

f597d6bb7b76b1089f434b8fc30dda74.png

图 8:拦截情况下输出

部分代码

最后,给出部分代码(两个用来构造包的函数),仅供大家参考。

from scapy.all import * content = '''HELLO WORLD '''

HTTP404 = '''HTTP/1.1 404 Not Found\r Server: 127.0.0.1\r Cache-Control: no-cache\r Content-Type: text/html\r Content-Length: %s\r %s ''' % (len(content), content) DF = 2      # Don't Fragment

RST = 4     # Reset

PA = 24     # Push, Acknowledgment

def genServerRstPack(pkg):

   pkgs = []    eDst = pkg.dst               # 以太网包 目的MAC地址    eSrc = pkg.src               # 以太网包 源MAC地址    dst = pkg.payload.dst        # IP包 目的IP    src = pkg.payload.src        # IP包 源IP    idn = pkg.id                 # IP包 id字段    tcpPayload = pkg.payload.payload    sport = tcpPayload.sport     # TCP报文 sport字段    dport = tcpPayload.dport     # TCP报文 dport字段    seq = tcpPayload.seq         # TCP报文 seq字段    nSeq = seq + len(tcpPayload)-4*tcpPayload.dataofs  

                                # 计算下一个包的 seq字段    for i in range(2):           # 通过上面的那些字段构造要发送的包                                 # TCP 的 flags 字段设置为 RST = 4         p = Ether(dst=eDst, src=eSrc)/IP(dst=dst, src=src, id=idn+1, flags=DF)/TCP(sport=sport, dport=dport, seq=seq,            window=0, flags=RST)/Padding("\x00\x00\x00\x00\x00\x00")        pkgs.append(p)    

   for i in range(3):        p = Ether(dst=eDst, src=eSrc)/IP(dst=dst, src=src, id=idn+2, flags=DF)/TCP(sport=sport, dport=dport, seq=nSeq,            window=0, flags=RST)/Padding("\x00\x00\x00\x00\x00\x00")        pkgs.append(p)    

   return pkgs

def genClientRstPack(pkg):    pkgs = []    eDst = pkg.dst    eSrc = pkg.src    dst = pkg.payload.dst    src = pkg.payload.src    tcpPayload = pkg.payload.payload    sport = tcpPayload.sport    dport = tcpPayload.dport    ack = tcpPayload.ack    seq = tcpPayload.seq    nSeq = seq + len(tcpPayload)-4*tcpPayload.dataofs       # tcpPayload.dataofs 为TCP首部长度,单位为4字节    p = Ether(dst=eSrc,src=eDst)/IP(dst=src,src=dst,flags=DF)/TCP(sport=dport,dport=sport,seq=ack,ack=nSeq,        window=65535, flags=PA)/Raw(HTTP404)    pkgs.append(p)    pkgs.append(p)    p = Ether(dst=eSrc,src=eDst)/IP(dst=src,src=dst,flags=DF)/TCP(sport=dport,dport=sport,seq=ack+len(HTTP404),        window=0, flags=RST)/Padding("\x00\x00\x00\x00\x00\x00")    pkgs.append(p)    pkgs.append(p)    

   return pkgs

11e232d90b686fa8d40ab502b2225921.png

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
axios请求拦截器在发送请求之前会拦截请求,并可以对请求进行一些处理。在这个例子中,我们可以看到拦截器的配置在引用中的`http.interceptors.request.use`函数中完成。该函数接受一个参数`config`,代表当前要发送的请求的配置。在这个函数中,我们可以根据需要对请求进行一些逻辑判断。 首先,我们可以看到在这个拦截器中定义了一个数组`noLanJie`,它包含了一些不需要被拦截请求地址。如果请求的地址在这个数组中存在,那么就直接放行,不做任何处理。 如果请求的地址不在`noLanJie`数组中,那么就是需要被拦截请求。在这个例子中,拦截器会从本地存储中获取到一个名为`token`的值,并将它添加到请求请求头中的`authorization`字段中。这样,在发送请求时,会将这个`token`作为身份验证信息携带到后端。最后,拦截器需要返回`config`对象,以便让请求继续发送。 总结起来,axios的请求拦截器可以在发送请求之前对请求进行一些处理,例如添加请求头信息等。拦截器可以根据请求的配置进行逻辑判断,决定是否拦截请求并进行处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [axios请求拦截器的配置](https://blog.csdn.net/qq_44603011/article/details/123121764)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [vue axios登录请求拦截器](https://download.csdn.net/download/weixin_38655810/13194829)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [axios全局拦截+请求响应处理+路由拦截](https://blog.csdn.net/weixin_42484657/article/details/122365109)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值