The sword of SEO

I was on a client server getting attacked, the DoS was heavily distributed. Since he’d mentioned something about someone linking to his web site, I was poking through the Apache logs. I noticed that one site was generating a huge amount of referrals. Investigating deeper, Ifound this on the referral site:

<iframe src=”http://www.domain.com” width=”1″ height=”1″ ></iframe>
0<br><iframe src=”http://www.domain.com” width=”1″ height=”1″ ></iframe>
1<br><iframe src=”http://www.domain.com” width=”1″ height=”1″ ></iframe>
2<br><iframe src=”http://www.domain.com” width=”1″ height=”1″ ></iframe>
3<br><iframe src=”http://www.domain.com” width=”1″ height=”1″ ></iframe>

…….

30<br><iframe src=”http://www.domain.com” width=”1″ height=”1″ ></iframe>

This is one of the slicker DoSes I’ve seen in a while. Because of the way it was set up it would be very difficult if not impossible to block on a network level and not traceable back to any particular IP on a network level (read:iptables, RTG or hardware firewall.) Within a few assumptions here this is what I believe to happen:

-Person sets up a web site with just a park page etc. on it.
-Person directs traffic to this using SEO. (back links, etc) to gain it status on search engines
-Person puts up the attack page similar to the above
-Every time a person from a search engine clicks the link, they load a few dozen copies of the page
-The iframe points to a “high value” target that generates a lot of load on the server, such as a forum or other dynamic content.

Backlinks are a crucial factor in the world of SEO. They are like a vote of confidence from other websites, indicating that your website is trustworthy and valuable. However, it’s essential to keep in mind that not all backlinks are created equal. High-quality backlinks from authoritative websites are worth more than low-quality backlinks from spammy websites. That’s why some people resort to buying backlinks to boost their website’s ranking. However, this is not a recommended strategy as it can lead to penalization from search engines like Google. Instead, it’s best to focus on building organic and high-quality backlinks through outreach and content marketing. Companies like Buybacklinks.club may offer to sell backlinks, but it’s important to proceed with caution and prioritize quality over quantity.

I personally saw this attack decimate a late model server with 16GB of RAM with enough IP distribution that it was not plausible to block it. It is viciously effective when planned out and done properly. It can also be done with virtually NO resources using a free shared hosting account. The person who loads it probably never realized they just made an attack on a server either. The plus side is that if you track it you can limit the damage done very easily provided you know what you are looking for. That will be my next blog.

Adding lots of IPs to a debian box

At work I had a client with a Debian system that needed a bunch of IPs added to it. Since it doesn’t really support ranges (at least that I can find) I came up with the following script.

#/bin/bash
j=42
for i in  {186..190}
do
j=$(expr $j + 1)
echo auto eth0:$j >> interfaces; echo iface eth0:$j inet static >> interfaces; echo address 192.168.41.$i >> interfaces; echo netmask 255.255.255.248 >> interfaces;
done

How it works is that j is the last IP in the ranges currently set in the interfaces file. The address is defined in the script, and the range is defined in the i= section. Just change the numbers to match what you want, put this into /etc/networking, run it and restart networking. This is only for five IPs but you could do hundreds or thousands this way if it was the desired affect. Or you can use a distro that supports ranges :>

Why you pay money for ECC RAM

Tonight presents a valuable lesson. I had a box running heavy MySQL duty that would crash at odd times. I could get MySQL to start, but the processes would die, it wouldn’t terminate cleanly, and even on a freshly started copy it was giving me “out of memory” errors. After fighting this for some time (say hours) and assuming that it was me the user, I checked the system in a bout of frustration.

Being a Xeon, my first look after rebooting it was in the error log of the BIOS. It had a lone ECC error in the log. Where I couldn’t even run show databases; before it will go through a check and stay up now. I bring this up as it presents two invaluable lessons:

A)It’s usually the software or the sysadmin that screws a server up. Not the hardware. That being said it is best to consider it. This is the second time I’ve seen a machine with ECC RAM screw up like this in two years and several hundred servers later. I have seen maybe 20 ECC equipped machines that actually had DIMMs that were bad. Probably half that. With that being said MySQL tends to show it first.

B)ECC RAM is worth the extra outlay in the datacenter. This could have easily not been detected for a long period of time, and cost a client and the next client that would have been put on the server.

How to set up DM-RAID drives in a rescue environment

After beating my head against a wall for a significant period of time because of a software RAID issue, I figured out how to set it up. Because it was so difficult I figure I would pass the savings on to you. OK here’s what we need to do. First thing is we need to figure out what our arrays are going to be made from. This is simply done with fdisk. After that we would vi /etc/mdamd.conf and add a line like this one:

DEVICE /dev/sdaN /dev/sdbN /dev/sdcN

and so on where sda/b/cN are the partitions our RAIDs are made of. Don’t worry about which is which mdadm will take care of that with the uuids.

Run this next:

mdadm –examine –brief –scan –config=partitions >> /etc/mdadm.conf

and it will put the information for the array into the config file. After this all we need to do is run:

mdadm -A /dev/mdN

for each device we want to set up. Mount as normal. Have a lot of fun

:^>

How to disable wordpress in a single query.

This is just a quickie I hijacked off another web site but it came in really handy since a client couldn’t access their wordpress admin panel and we don’t really support it. Just log in to SSH or PHPMyAdmin and run the query that follows:

wp_options SET option_value = ” WHERE option_name = ‘active_plugins’;

*BOOM* no more WP plugins. Then if you’re troubleshooting it go through and reactivate till it breaks again. If not tell em they are on their own.

If you are doing this via SSH you will need to go into the MySQL shell. That can usually be done by typing “mysql” or “mysql -u username -p” and entering the password for the user. If you need this you can grab it from wp-config. After that you need to select the db to use. You do that by going:

mysql>use dbname_here;

This will put you into the appropriate db. Then you run the query above. This is of course assuming you’re using the default schema for naming the tables. If  you are not wp_options needs to be changed to just “options” or schema_options as necessecary. If you don’t know what your schema is you can do:

mysql>show tables;

What Chattr can do for you

Chattr is one of those great utilities in a security tool box. Since log files are a prime target of removal when root kits and other scripts are used on a system after the compromise, it’s an ideal way to help prevent destruction of the logs. Besides this, if you don’t want certain files tampered with you can use chattr to make them non writeable by anyone including root. This is done at a file system (inode) level regardless of what is there. My favorite options are:

+a. This sets a file append only. This is great for logs, and will catch a lot of script kiddies off guard. If overwriting of data is attempted it will deny the operation. as an example:

[root@DNS02 ~]# chattr +a ./new.file
[root@DNS02 ~]# echo “aghaklsjdfhadlwadjhad” >> new.file
[root@DNS02 ~]# echo “aghaklsjdfhadlwadjhad” > new.file
-bash: new.file: Operation not permitted

Since the first echo adds it to the end it will work. The second echo attempts to overwrite the file contents so it gives a permission error. Please note that this is even though the user has full permissions to access the file. to reverse this we use chattr -a new.file

The +i function is a little different, it will make the file totally unchangeable. If we have binaries that we consider sensitive this may be an option for it. I have had systems I needed to get back up with rootkits that would change files on the boot, this would take care of bringing them back up without allowing whatever was on the system to modify it.

The +u option allows for undeleting of files, this is another thing that may be good for sensitive information such as logs or key backup archives. Would be tempted to use it with +a as well for logs.

The +c option gives the files on disk compression. Never really played with it much however I would think it could be detrimental with large archives on RAM and CPU bound systems.

Why not to use a downloaded my.cnf part II

In case you don’t recall or weren’t reading when it was put up, I did an article on why a downloaded my.cnf is a bad idea. It’s time for a bit of appending to that. I am cranking out my usual support tickets helping little old ladies with their sites about their pinochle groups (no not really) when I get a support ticket from a client who is having issues with their databases not working properly.

Naturally, being the curious sort I am and them being a paying client, I log into the server and start examining things. The first thing I do is try to do a database check. This doesn’t go over too well, I get a bunch of errors about “corrupt .frm files.” Naturally my curiosity is piqued at this point, so I go and start looking through /var/lib/mysql/hosts.err file. What is extremely odd here is that there it is super short, and there is nothing there really. At this point I decide to log into mysql and try rotating out the log file. It indicated that the operation had completed successfully, so I am a bit baffled at this point. Looking in the my.cnf, it appears that someone downloaded a web based my.cnf and stuck it on the server. It also appears that the logs are going somewhere else at this point. After examining the correct logs, I find a bunch of errors about the .frms being corrupted. I then start looking for the MYIs so that I can see if I can rebuild the .frms with them. To my dismay I find out there are no MYIs for the DBs here just the .frms.

After updating the client on what I’d found, I start looking over the net for an answer. It turns out that if InnoDB doesn’t have the engine started it will default to MyISAM databases, which is where the .frms came from. Definitely getting closer at this point, so I start looking at the engine statuses and of course InnoDB is disabled.

After this the picture is starting to come into focus a bit more, something in the my.cnf was changed and it broke everything. But what? I had noticed that the server was running MySQL as root when I had done “ps aux | grep mysql” earlier so I had a suspicion. Referencing another server I confirmed what I thought and found out that a line was missing.

user=mysql

The net downloaded configuration didn’t have a set MySQL user, root didn’t have permission to access the file and therefore it wouldn’t load the InnoDB files and in turn the InnoDB engine. A single line was missing and this production server was likely down for hours while they tried to figure out what happened. The internet is not a substitute for knowing what you are doing. Yes it can help you in this regard, but at the same time it is not a substitute for knowledge or competency. I once had an instructor tell me there is no crib sheet for life, it rings as true now as it ever did when he said it.

IO scheduler tuning in Linux

This is my personal FS box. It consists of 4X200GB SATA drives on an Adaptec AAR-2810 controller in RAID10. I am using bonnie++ to benchmark. The reason I am throwing this up is that when I switched schedulers to deadline with 3 drives in a RAID5 on this system (I changed to a 10 later) it picked up about 5% by going to a deadline scheduler in sustained writes. If you notice in this case while I had a few small gains aggregately I lost a significant amount of performance at one point or another compared to the default scheduler. Then again, this array has write performance at a level typical of a single drive if not a little slower. It makes up for it in the fact that it has roughly double the read of a typical drive, which can be far more important depending on the application. Since it’s just a dump box anyways I’m not overly concerned about IO. Check the results out and post your opinions. I will probably add other tuning specifics at a later date. Please note this does not under any circumstances make CFQ my preferred scheduler; it just means it was better in this case.

cfq (default)

Version 1.03e ——Sequential Output—— –Sequential Input- –Random-
-Per Chr- –Block– -Rewrite- -Per Chr- –Block– –Seeks–
Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
FS01.robotone 1000M 34694 88 39045 27 19030 8 36912 68 63545 12 496.2 1
——Sequential Create—— ——–Random Create——–
-Create– –Read— -Delete– -Create– –Read— -Delete–
files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
16 19929 100 +++++ +++ 32373 99 +++++ +++ +++++ +++ +++++ +++
FS01.robotonet.com,1000M,34694,88,39045,27,19030,8,36912,68,63545,12,496.2,1,16,19929,100,+++++,+++,32373,99,+++++,+++,+++++,+++,+++++,+++

echo deadline > /sys/block/sda/queue/scheduler

Version 1.03e ——Sequential Output—— –Sequential Input- –Random-
-Per Chr- –Block– -Rewrite- -Per Chr- –Block– –Seeks–
Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
FS01.robotone 1000M 30986 88 38772 31 16724 7 29545 56 62167 11 482.5 1
——Sequential Create—— ——–Random Create——–
-Create– –Read— -Delete– -Create– –Read— -Delete–
files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
16 20401 99 +++++ +++ 26963 99 29849 99 +++++ +++ +++++ +++
FS01.robotonet.com,1000M,30986,88,38772,31,16724,7,29545,56,62167,11,482.5,1,16,20401,99,+++++,+++,26963,99,29849,99,+++++,+++,+++++,+++

echo anticipatory > /sys/block/sda/queue/scheduler

Version 1.03e ——Sequential Output—— –Sequential Input- –Random-
-Per Chr- –Block– -Rewrite- -Per Chr- –Block– –Seeks–
Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
FS01.robotone 1000M 33134 94 38153 28 17225 8 30326 58 65073 10 346.8 0
——Sequential Create—— ——–Random Create——–
-Create– –Read— -Delete– -Create– –Read— -Delete–
files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
16 19071 94 +++++ +++ +++++ +++ +++++ +++ +++++ +++ +++++ +++
FS01.robotonet.com,1000M,33134,94,38153,28,17225,8,30326,58,65073,10,346.8,0,16,19071,94,+++++,+++,+++++,+++,+++++,+++,+++++,+++,+++++,+++

echo noop > /sys/block/sda/queue/scheduler

Version 1.03e ——Sequential Output—— –Sequential Input- –Random-
-Per Chr- –Block– -Rewrite- -Per Chr- –Block– –Seeks–
Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
FS01.robotone 1000M 29617 86 39779 27 16359 7 29197 57 62977 10 496.6 1
——Sequential Create—— ——–Random Create——–
-Create– –Read— -Delete– -Create– –Read— -Delete–
files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
16 20130 99 +++++ +++ +++++ +++ +++++ +++ +++++ +++ +++++ +++
FS01.robotonet.com,1000M,29617,86,39779,27,16359,7,29197,57,62977,10,496.6,1,16,20130,99,+++++,+++,+++++,+++,+++++,+++,+++++,+++,+++++,+++

Basic MySQL backups

Backing data up in MySQL is super important. The site content is often replaceable, however your board posts, ecommerce orders, etc. are far far harder to replace, if at all possible. The other nice thing is that with a lot of database driven web sites you retain most content even if you only back up the databases. You can still lose things like images, but by and large your posts will still be there even in event of a crash. Since bad code, etc. happens there are a few reasons I would recommend doing backups of the databases.

  • Making server side changes, including configuration tweaks that can influence system stability.
  • Making software changes, even adding plugins etc. to your site. I have seen odd things in the past caused by plugins and they can interact together with not always predictable results.
  • Periodical backups as part of a data protection plan. I would do more than less, by and large most databases are not huge for the data they contain. I have seen forums with about 100,000 posts have about 2GB of database; not really that much if you think about it.

There are a few ways to do backups, but the most common for people who don’t use command line interface is probably going to be PHPMyAdmin. Quite frankly, I do not like using it for database backup and restorations. There are two reasons for this pertaining to reliability

  • If the session timeout of PHP or Apache is too low, you will get an incomplete dump. This means that backup you may have of your databases is all of a sudden found to be truncated at a few megabytes. This is not a big deal for a lot of people with small DBs however if you’re rocking out with 50+ megabyte DBs this can be a huge issue.
  • Restoration can be dependent on if the person has large uploads and large timeouts enabled. Since most people have slower upload than down, it can be a real nuisance to get the DB back up to the server and restored. Not only that but If you have a server with low upload size limits and timeouts, it may be impossible to get that DB back up and restored to the system before you hit one of these limits.

The way I honestly prefer to back my databases up is mysqldump; this allows one to have a lot of control over what gets dumped, do a full backup without worrying about doing it individually etc. It also allows us to make a nice easy cron job to do these backups too if we want.

The way we back a particular DB is up is:

mysqldump dbname > backup.sql

This will put the database named dbname into backup.sql. I believe you can separate multiple DBs with a space as well, however I don’t normally use that functionality. Another thing you can do is you can back up everything with:

mysqldump --all-databases > backup.sql

and this will do everything on the server. Handy for migrations, etc. Definitely way easier than trying to do this via a web interface and having 1,000 DBs.

How we restore these is fairly simple as well, we just run the command as follows:

mysql dbname < backup.sql

If you have a full DB dump you wouldn’t specify anything for the name when restoring. Notice how the carrat points in the opposing direction though. Don’t screw this up otherwise you will likely end up with a blank file and have to re-dump or re-move the file. I usually make 2 copies on the destination server especially when it’s not easy to get a second copy. There are other ways of moving the DBs over, such as copying the raw MYI files but that will be another blog.