
在发布新服务之前,很高兴确保它能够按照我们的期望运行并且无论有多少客户同时使用它都可以使用。
如果针对它组织了分布式DoS攻击,该服务将如何反应? 资源是否受到潜在攻击者的保护?
为了评估可能的风险并提高安全性,在尚未启动用于大规模使用的资源时,独立执行模拟DDoS攻击的措施是有意义的。
在本文中,我们将讨论组织DNS和HTTP服务的负载测试的经验。
准备工作
为了在监视的资源上产生大量的网络流量,您需要使用许多虚拟机,每个虚拟机都会向服务发送最大数量的请求。 如果您没有功能强大的数据中心,则可以在云中临时租用虚拟机。 这个想法具有一个特征:您需要确保云不会爬网,将您的活动用于攻击者的行为。
比较使用其功能进行负载测试的各种云服务的策略(无情地禁止某个帐户,该帐户可能导致资源失败),我们决定停止使用Amazon Web Services (AWS)。 他们的文件表明AWS允许进行负载测试,但通过将电子邮件发送到特定地址来请求批准。
压力测试的协调
我们发送一条消息,在其中简要讨论我们的意图,并获得必须填写的表格:
Customer ID: Customer Name: Email Address: AWS Account ID load test will be performed from: Does the customer have an NDA? Target Data EC2 Resources: Cloudfront Distribution: API Gateway / Lambda ID: ELB Names: Non-AWS Target: Region (please list all regions in scope for testing): Source Data: IP Addresses: Source Account ID: Regions involved: Testing Parameters: How much traffic do you plan to generate by region during testing? What is your expected peak load from source by region? (ie xx Gbps) What is your expected peak load at destination? (ie xx Gbps) Are you testing traffic outbound from EC2, inbound into EC2, or both? Are you testing traffic outbound (egress) from EC2, inbound (ingress) into EC2, or both: Egress. What is your expected peak load from source by region? (ie xx Gbps) Ingress. What is your expected peak load from source by region? (ie xx Gbps) Start Date: End Date: Finite testing details including timeline of testing: Summary of Test: Testing Timelines by phase including rps, pps, and Gbps: Peak bandwidth for each source IP: Tools Used for each phase of test: Types of testing to be performed for each phase of the request: What criteria/metrics will you monitor to ensure the success of this test? Who is performing the Load Test? (Please provide contact details): Does the tester have an NDA? Testing Security Do you have a way to monitor the data traffic for the duration of the test to verify bandwidth limits do not exceed approved rates? Do you have a way to immediately stop the traffic if we/you discover any issue? 2 Emergency contact names and phone numbers:
有几个细微差别:
他们问我们谁将“晒黑”。 我们对此有权利吗? 我们说这是我们的资源(显然,没有人检查是否如此),并且测试是完全一致的。
我们需要指定将在每个区域中创建多少流量。 在通信过程中,我们发现每个区域都有自己的网络流量限制。 总共允许他们请求645 Gb / s。 我们考虑了攻击所需的数量,然后选择区域以获取必要的值。
需要描述攻击将在什么时间进行,持续多长时间以及其功率将如何增长。 我们以自由形式,但有足够的细节谈论我们的计划。 攻击是在逐渐增加功率的情况下进行的,因此我们绘制了测试将进行的阶段以及每个阶段预期的最大功率。 攻击日期最多可以省略一天;很可能会指出两到三周的范围。
毫无疑问,我们将竭尽所能,以确保我们表现良好,仔细监控测试进度,并在必要时在首次提出要求时停止测试。
在完成表格后,他们很可能会要求您做一些澄清,因此我们会回信并回答问题,直到获得测试许可。
如果及时回答,则大约需要三个工作日才能完成批准过程。
基础设施准备
批准后,我们面临准备测试基础架构的需求。 事实是,在检查过程中,我们需要及时:
•包含一个实例;
•发起测试攻击;
•收集进度统计信息;
•停止测试攻击;
•更改IP地址;
•关闭实例。
创建实例映像
选择实例类型
首先,让我们构建一个AWS映像,其中将包含用于管理的必要工具和脚本。 第一步是选择要租用的实例。 我们研究了不同类型实例的特征:我们查看价格,最大流量,CPU能力(后者很重要,因为流量毕竟是由处理器的容量创建的),然后我们测试实际性能和最大请求数。 根据我们的估计, t3.small
实例最方便测试,但是每个人都可以选择自己的口味。
实例的特征可以在这里找到。 您也可以在此处选择和比较实例。
限制要求
您需要事先考虑多少个实例将参与测试。 事实是,Amazon为每个区域提供了实例数量的限制。 如果您感觉需要的实例数将超过默认情况下的实例数,那么您应该尽早请求增加限制。 为此,请转到“ 支持”部分,创建“服务限额增加”类型的呼叫。 请求的处理时间可能有所不同:某人第二天回答,提供了所请求的尽可能多的实体,某人说他最多允许运行N个实例。 有一些地区对请求的回应大约一个月。
性能调优
接下来,您需要创建一个在测试期间启动的实例映像。 为此,我们打开选定类型的实例,对其进行所有设置,然后将发生的情况保存为图像(在“动作”菜单中,您可以在其中启用该实例,以及创建图像的功能创建图像)。
我们需要从每个实例获得最大的传出流量,因此首先我们针对实例上的任务优化网络和内存设置。
为此,请在/etc/sysctl.conf
文件中进行设置:
•增加本地端口的范围并减少处于FIN_WAIT状态的套接字所花费的时间:
net.ipv4.ip_local_port_range = 1024-65535 ( : 32768-61000) net.ipv4.tcp_fin_timeout = 10 ( : 60)
本地端口范围确定主机可以从特定IP创建的最大出站套接字数。
使用默认设置(61,000–32,768),可获得28,233个套接字。 使用新设置-64500。
Fin_timeout定义传出套接字可以处于FIN_WAIT状态的最短时间。
如果指定了默认值,则系统每秒最多只能提供(61,000–32,768)/ 60 = 470个套接字。
通过增加port_range和减少fin_timeout,我们可以影响系统生成更多传出连接的能力。
•让我们在空闲的套接字结束时重用处于TIME_WAIT状态的套接字:
net.ipv4.tcp_tw_reuse = 1
设置以上选项(默认情况下处于禁用状态)有助于最大程度地减少已实现的“空闲”连接的丢失。
本文介绍了有关TIME_WAIT的非常详细的信息。
•打开tcp_timestamps选项以使上述tcp_tw_reuse选项起作用:
net.ipv4.tcp_timestamps = 1 – `tcp_timestamps` tcp_tw_reuse
•其他选项:
net.ipv4.tcp_max_tw_buckets = 720000 – TIME_WAIT net.ipv4.tcp_keepalive_time = 600 – - keepalive- net.ipv4.tcp_keepalive_probes = 3 – keepalive- net.ipv4.tcp_keepalive_intvl = 10 – keepalive- net.ipv4.tcp_window_scaling = 1 – TCP- net.ipv4.tcp_mem = 8192 131072 196304 – TCP- net.ipv4.udp_mem = 8192 131072 196304 – udp- net.ipv4.tcp_slow_start_after_idle=0 – Slow-Start Restart net.core.wmem_default = 31457280 – net.core.wmem_max = 33554432 – net.core.somaxconn = 65535 – net.core.netdev_max_backlog = 65535 – vm.swappiness = 30 – vm.dirty_ratio = 50 – 50 % vm.pagecache = 90 –
测试攻击脚本
1. DNS攻击
测试的主要任务之一是评估DNS服务器的性能。 也就是说,DNS服务器可能成为站点容错的瓶颈,因为即使DNS存在问题,即使最稳定的服务也无法使用。 为了在DNS服务器上创建负载,我们将生成许多不同的DNS查询。 请求必须有效,并且需要DNS服务器提供最大可能和最长响应。
DNSPerf实用程序适用于生成此类流量。
DNSPerf是一种简单,灵活且免费的DNS性能测试工具。 它主要是为权威DNS服务器设计的,但也可以用于衡量缓存服务器的性能。
在我们的情况下,将加载服务于一个区域(example.com)的权威DNS服务器。
对于DNSPerf,我们首先准备一个带有dns_queries.txt
请求的文件(主要是ANY,以增加来自DNS服务器的响应的时间和大小):
#dns_queries.txt example.com ANY www.example.com ANY test.example.com ANY static.example.com ANY example.com www.example.com test.example.com MX
运行该实用程序的示例:
dnsperf -s TARGET_IP -d dns_queries.txt -c 100 -n 100 -s = IP- -d = . – stdin -c = . -n = «» .
2.攻击ICMP
下一步测试是评估对大量ICMP流量的抵抗力。 由于出于技术原因,服务器通常需要能够响应ping请求,因此存在使用ping请求进行DDoS攻击的可能性。 除了指定排除ping-to-death
可能性的设置外,您还需要确保服务器能够抵抗峰值ICMP负载。 要创建此类负载,最好使用众所周知的hping3实用程序,该实用程序可让您调整请求数,发送间隔和数据包大小。
运行该实用程序的示例:
hping3 -i u1000 -d 1500 -c 100000 -1 TARGET_IP -i u100 = (uX for X microseconds) -d 1500 = -c 1000000 = -1 = ICMP
3. HTTP攻击
现在,我们检查压力的主要功能是服务的主要功能-处理HTTP(S)流量。 围攻是产生HTTP流量的最灵活和最简单的工具之一。 Siege是一个开源多线程实用程序,旨在测试Web资源的性能。
与DNSPerf一样,siege允许您向服务器加载来自给定数量的虚拟用户的请求(用户仿真是使用单独的端口进行的),以及使用一组预定义的请求。 这非常方便,因为您可以在测试中包括最耗费资源的查询。
运行该实用程序的示例:
siege -b -c 100 -f test_urls.txt -b = ( benchmark) -c = . -f =
内容格式test_urls.txt
:
http://example.com/site/login POST login=username&password=test http://example.com/site/client POST useragent=Mozilla&version=123&date=24May http://example.com/site/order POST user=username&company=ooo&phone=812345678
如您所见,测试主要是使用POST请求执行的,与其他类型的请求相比,这些请求需要在服务器端进行处理并占用最多的资源。
所有选项均不使用IP欺骗,因为Amazon不允许这样做。 无论软件包中指定了什么src_IP,它都将在从实例退出时更改为正确的src_IP。
所有生成的请求都必须是合法的-没有任何待解决的外向流量-因为Amazon的DDoS策略非常严格。 即使是经过协调的压力测试,也至少需要几天才能与技术支持进行沟通,并且在第一个“恶意”行动中,我们禁止了流量从该港口驶出,并立即解释了这一要求。
发起攻击的脚本
对于远程测试管理,我们将准备启动所需攻击类型的bash脚本(dns.sh,ping.sh,http.sh)和有效负载文件(test_urls.txt,valid_dns_queries.txt)。
当我们将所有这些都上传到AWS映像(从中将创建所有实例)时,可以使用以下格式的命令远程运行每个测试:
ssh instance-amazon 'sudo <stress-script>.sh start <params> &>>stress.log &'
所需类型的脚本被指定为Stress-script.sh,而params是相应的参数。 在Stress.log文件中,我们将跟踪正在运行的实用程序的输出。 为了方便起见,我们将为不同的实用程序使用不同的日志:dns.log,ping.log,http.log。
dns.sh
脚本示例:
从代码中可以看出,脚本可以启动和停止,以及检查状态(运行/不运行)。
用于ICMP和HTTP测试的脚本以相同的方式构造,分别通过传递给参数的参数字符串开始hping3和siege。
命令示例:
ssh instance-amazon 'sudo dns.sh start -s TARGET_IP -d valid_dns_queries.txt -c 1 -n 100 &>>dns.log &' ssh instance-amazon 'sudo ping.sh start -i u1000 -d 1500 -c 100000 -1 TARGET_IP &>>ping.log &' ssh instance-amazon 'sudo http.sh start -b -c 100 -f test_urls.txt &>> http.log &'
监控脚本
要评估传出的流量和测试基础结构的状态,我们需要一个监视工具。 为了简单和节省资源,我们使用iptables。 为此,我们将编写一个脚本来计算发送的MB数,并将其放在AWS映像上:
#iptables.sh sudo iptables -N TRAFFIC_OUT sudo iptables -A TRAFFIC_OUT -p tcp sudo iptables -A TRAFFIC_OUT -p udp sudo iptables -A TRAFFIC_OUT -p icmp sudo iptables -A OUTPUT -j TRAFFIC_OUT sudo iptables-save
该脚本会创建一个新链TRAFFIC_OUT,并为必要的协议(tcp,udp,icmp)添加过滤器。
数据包转发到TRAFFIC_OUT已添加到OUTPUT链中。
可以通过以下命令找到传输的数据量:
# iptables -L TRAFFIC_OUT -v -n -x | tail -n 3 | awk '{print $2/1024/1024,"Mb\t\t\t",$3}' : 2.2 Mb tcp 4.4 Mb udp 3.2 Mb icmp
将脚本作为服务安装。 为此,创建一个monitoring.service文件并将其移动到我们映像的/etc/systemd/system
目录中:
# /etc/systemd/system/monitoring.service [Unit] After=network.target [Service] ExecStart=/usr/local/bin/monitoring.sh [Install] WantedBy=default.target
现在,您可以将服务添加到启动中:
systemctl enable monitoring.service systemctl start monitoring.service
实例管理
现在让我们处理远程(尽可能自动化)的实例管理。
为此,您可以使用AWS CLI机制-控制台管理。
创建一个秘密密钥 (访问密钥(访问密钥ID和秘密访问密钥))并配置控制台。
现在,我们可以访问该帐户的所有功能。
使用AWS的独特之处在于,所有操作都是针对特定区域执行的,如果涉及多个区域,则必须重复执行所有操作。
要从上面构建的图像创建一个新实例(假设脚本中使用了公共ami-ID),我们将执行以下操作:
yes n |ssh-keygen -q -t rsa -f $KEYNAME -m pem -N "" > /dev/null chmod 400 $KEYNAME aws ec2 import-key-pair --region $REGION --key-name $KEYNAME --public-key-material file:///$(pwd)/$KEYNAME.pub
- 创建一个安全组,该安全组允许通过SSH访问计算机。 否则,传入的SSH连接将被拒绝:
SECURITY="ssh-group" aws ec2 create-security-group --region $REGION --group-name $SECURITY --description "Just ssh. Nothing more" IP_RANGE="0.0.0.0/24" aws ec2 authorize-security-group-ingress --region $REGION --group-name $SECURITY --protocol tcp --port 22 --cidr $IP_RANGE
- 使用先前创建的密钥和安全组创建一个实例,并指定映像ID。 一次创建的实例数可以是任意的:
IMG='ami-0d0eaed20348a3389' NUM=1 aws ec2 run-instances --region $REGION --image-id $IMG --count $NUM --instance-type t2.micro --key-name $KEYNAME --security-groups default $SECURITY > instances.json
- 等待机器初始化。 这需要一些时间:首先我们获得成功响应(instances.json),但是那时机器只是创建但尚未启动(例如,尚未分配IP地址)。 必须等待启动完成(通常一分钟就足够了)。
然后,如果我们知道IP地址,则可以通过SSH连接。 只需索取当前正在运行的计算机的列表即可。 在它们的参数中,我们找到PublicDnsName或PublicIpAddress。
aws ec2 describe-instances --region
接下来,我们执行SSH命令,指示上面创建的SSH密钥:
ssh -I $KEYNAME -oStrictHostKeyChecking=no ubuntu''+ins_dns echo''O''
SSH命令使您可以控制攻击并获取有关攻击状态的所有信息,因为我们为实例提供了所有必需的脚本和工具。
您需要了解,大多数针对拒绝服务攻击的防御措施都会阻止从异常地接收到许多请求的IP地址。 因此,虚拟机的IP地址必须不断更改,以保持攻击能力。
每次机器启动时,AWS都会分配一个新的IP地址。 因此,要更改IP,您需要先关闭机器然后再打开(无需将其删除!)。
关闭和删除之间的区别在于我们发送不同的信号。 停止-关闭,终止-关闭并立即删除。
为了监视实例的传入流量,我们使用以下带有实例ID的命令:流量测量开始时,测量结束时,将值累加多少时间:
aws cloudwatch get-metric-statistics --region REGION --namespace AWS/EC2 \ --statistics Sum --metric-name NetworkIn --start-time $STARTTIME --end-time $FINISHTIME --period $PERIOD --dimensions Name=InstanceId,Value=$INCTANCEID
服务可用性监控
此外,要进行攻击,您将需要观察我们正在测试的服务是否仍然有效。
我们创建并运行最简单的“ ping”脚本来监视目标端口的可用性(在本例中为53和80)。
自动执行可用性检查的示例Python代码:
def http(url): cmd = ['curl', '-w', '"%{time_total}"', '-o', '/dev/null', '-s', url] result = check_output(cmd).decode('utf-8') result = float(json.loads(result)) return result * 1000000 def dns(ip, domain): cmd = ['dig', 'any', '@'+ip, domain ] result = check_output(cmd).decode('utf-8') result = int(result.split('Query time:')[1].split('msec')[0]) return result
接收到的信息存储在日志文件中,在此文件的基础上,根据攻击结果,可以构建资源可用性图。
在测试过程中,有必要不断检查“ ping”日志,以免完全和不可挽回地杀死资源。 一旦出现严重降级并且对请求的响应花费了太多时间,就必须停止攻击。
如果速度下降不明显,并且攻击强度已达到既定的最大值,则等待一两分钟是有意义的;如果服务继续正常运行而没有中断,则认为检查成功。
财务问题
值得讨论与测试组织有关的另一个问题-整个事件的成本。
亚马逊提供了详细的价格信息,但您需要了解您几乎必须支付所有费用。 但是,许多计算可以忽略。 首先,值得计算流量成本(取决于区域和要传输的信息总量)和租用实例的成本(每分钟支付)。 这些物品约占整个攻击成本的99%。
因此,根据[敌对规模]最大攻击力和计划发射的次数,分别计算攻击成本。
从简化计算的角度来看,最好使用不超过一年前注册的亚马逊帐户。 然后,部分操作将是免费的。 在此处阅读有关免费使用限制的更多信息。
为了说明进行负载测试的成本的计算方式,假设我们要检查DNS服务器在10 Gb / s负载下的稳定性。
我们知道,在孟买启动的t3.small实例使用的工具和功能使您可以从一个正在运行的实例发出500 Mb / s的速度。 租用实体的价格为每小时$ 0.0224,用于流量-1 GB为$ 0.01093。 即,攻击高峰意味着同时运行20个实体。
我们将逐渐增加攻击力,为此,我们首先发射一个实体,然后每60秒增加一个实体。
计算成本的公式采用以下形式:
60 * ( ) + 60 * 0,5 /c * ( ) = 60 . 1 * ( ) + 2 * ( ) + ... + 20 * ( ) =
事实证明,对DNS服务器进行容量为10 Gb / s的攻击的成本约为70美元。 请注意,这是一个粗略的估计,因为无法准确预测流量。 . , – , .
. .