The DDoS attack on net 44 continues. I'm filtering out a goodly amount
of it at amprgw, but the people whose subnets are directly connected (BGP
announced) are getting hit too, and there's nothing I can do to filter it
out here. Basically, if you're directly connected (ie, not on a tunnel),
you have to add a list of bad guys to your own firewall blocking.
Here is a little script that will create a list of candidate addresses
for blocking. You'll need the 'badguys' program, which I'll post below.
What this does is give you a list of addrsses that sent you more than
1000 packets in the sample period.
If you're connected via tunnel, you probably don't need this.
I run this several times a day to accumulate a list of bad guys.
I sample 100 million packets at a time; smaller subnets will probably
want to use a smaller sample size.
This was developed on FreeBSD but I'm told it works fine on Linux
Hope this helps.
- Brian
-----------------------------------------------------------
block.sh:
#!/bin/sh
#
# generate a list of possible bad guys
#
# sample incoming traffic, 100,000,000 incoming packets
# during DDoS storm on a /8, this takes about 3 minutes
time tcpdump -w /tmp/t.pcap -s 40 -c 100000000
# turn into a list of source IP addresses with counts,
# sorted by decreasing count
# throw away all those counted less than 1000,
# delete the count from the line
# elide our own addresses (put your own in the egrep)
# store in a file
./badguys /tmp/t.pcap \
| sort \
| uniq -c \
| sort -rn \
| sed -e '/^ /d' \
| sed -e 's/.* //' \
| egrep -v '^44\.|^169\.228\.' \
/tmp/badguys
# all done with this file
rm -f /tmp/t.pcap
exit 0
-----------------------------------------------------------
badguys.c:
/*
* reads pcap capture file (use tcpdump -w to create) named
*
* spins through it, listing the IP source address on stdout
* prints summary statistics on stderr
*
* the documentation on the pcap library leaves a lot to be
* desired, use the source. a lot of what you need is in tcpdump.c
*
* compile me with
* cc -g -Wall badguys.c -lpcap -o badguys
*
* (You'll need to have libpcap installed)
*
* Brian Kantor, UCSD, 2017
*/
/* probably most of these includes are superfluous */
#include <sys/errno.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <pcap/pcap.h>
#include <pcap/bpf.h>
void getpkt(u_char *, const struct pcap_pkthdr *, const u_char *);
char * iptoa(u_long);
int capcount = 0;
int skipcount = 0;
int
main(int argc, char**argv)
{
char inpcapname[FILENAME_MAX+1];
char errbuf[BUFSIZ];
pcap_t *pcap;
int rslt;
if (argc != 2) {
fprintf(stderr, "Usage: %s pcapfilename\n", argv[0]);
exit(1);
}
strncpy(inpcapname, argv[1], FILENAME_MAX);
fprintf(stderr, "opening PCAP file %s\n", inpcapname);
pcap = pcap_open_offline(inpcapname, errbuf);
if (!pcap) {
fprintf(stderr, "Error: %s\n", errbuf);
exit(1);
}
/*
* read through the capture savefile
*/
rslt = pcap_loop(pcap, 0, getpkt, 0);
if (rslt) {
fprintf(stderr, "pcap_loop returned %d\n", rslt);
pcap_perror(pcap, "pcap_loop returned");
exit(1);
}
pcap_close(pcap);
fprintf(stderr, "%d packets read from savefile\n", capcount);
fprintf(stderr, "%d non-IP packets discarded\n", skipcount);
exit(0);
}
/*
* called by pcap_loop once per packet read from savefile
*/
void
getpkt(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
struct ip * ip;
u_short * ethertype;
capcount++;
/* get the Ethernet packet type */
ethertype = (u_short *)&p[(2*ETHER_ADDR_LEN)];
/* we only want IP packets */
if (ntohs(*ethertype) != ETHERTYPE_IP) {
skipcount++;
return;
}
/* IP packet starts after Ethernet header */
ip = (struct ip *)&p[ETHER_HDR_LEN];
puts(iptoa(ntohl(ip->ip_src.s_addr)));
return;
}
/*
* nicely format host-byte-order u_int into dotted quad
* returns pointer to a small static buffer; you can't
* call this more than once in a single syslog or printf statement
*/
char *
iptoa(u_long ipaddr)
{
static char buf[32];
snprintf(buf, sizeof buf, "%lu.%lu.%lu.%lu",
(ipaddr >> 24) & 0xff,
(ipaddr >> 16) & 0xff,
(ipaddr >> 8) & 0xff,
(ipaddr) & 0xff);
return buf;
}