grep only stderr from a command
So sometimes you have a command where you want to only grep stderr. For example I use Cronic to manage all my cronjobs. It’s really nice since it sends a nicely formatted email back to you if a command returns anything in stderr. Crontab alone will email me if anything in stdout/stderr is printed out from a command.
There is a problem with cronic though. There’s an app called s3cmd which uploads files to s3 and on large files this output can happen
WARNING: Retrying failed request: /postgresql/2013-05-05_hour-18.sql.bz2?partNumber=1&uploadId=m0gX4xcOU7IDla2B2p55xJXDfih_mm7rDx5bJvucUAmQYC10mwoHXVDjyoat_uzNJBYpedrWu7neakUpH3zGw-- ([Errno 110] Connection timed out)
WARNING: Waiting 3 sec...
This generally happens if the fule is very large. s3cmd will restart the transfer of the part and it will be uploaded just fine. So the main issue is s3cmd has no way to ignore warnings, at least as of 1.5.0-alpha2. If it does, I am overlooking it.
So in order to solve this I have decided I want to grep out the WARNING lines from stderr. Now the easy way to do this is re-direct stderr to stdout and pipe it to grep. Well this sucks cause you will lose valid error output. So the answer is something like this
cmd 2> >(grep -v "WARNING" >&2)
That will then allow you to grep just from stderr and the -v flag will set grep to ignore WARNING lines.
Remove internal hosts in postfix
A proper way to setup your network is to have a postfix relay server sitting somewhere on your network that every other server has access to via port 25. Now your relay server(s) are the only ones that should have outside access to port 25. All other servers should be firewalled off!
So for example say your email chain looks like this for a new signup
web1.domain.com -> mailserver.domain.com -> internet -> user's mailbox
If the user views the email source they will see that the email started at web1.domain.com and it will include your internal IP address. So you are exposing internal IP addresses which isn’t very good at all.
So we can fix this in postfix very easily on the mailserver.domain.com config. For example say your internal network is
10.114.0.0/16
So lets remove them everything in that subnet along with 127.0.0.1. So edit the following file
/etc/postfix/main.cf
Then add the following line
header_checks = regexp:/etc/postfix/header_checks
Now create a new file
/etc/postfix/header_checks
Then add the following in place
/^Received:.*\[127\.0\.0\.1/ IGNORE
/^Received:.*\[10\.114\..*/ IGNORE
Then restart postfix and you are good to go.
How many bits per point in a whisper file in graphite
This is an easy one. You do an ls over a whisper file and get something like
1.1M -rwxr-xr-x 1 root root 1.1M Aug 9 11:06 Active.wsp
Now you are planning to save more metrics in your graphite server or want more points in your retention so you want to plan how much space you’ll need given an estimated guess of your metric count out 6 months from now. So you can run the following over that whisper file to get info on it.
$ whisper-info.py Active.wsp
maxRetention: 31536000
xFilesFactor: 0.5
aggregationMethod: average
fileSize: 1062772Archive 0
retention: 604800
secondsPerPoint: 60
points: 10080
size: 120960
offset: 52
So you see for Archive 0 we have a certain size and number of points. So from here it’s easy math
120960 / 10080 = 12
So for each whisper data point you save it will allocate 12 bits on your filesystem. So you can plan our growth since carbon pre-allocates the space needed for whisper files so your disk isn’t doing any random seeks while pulling up data for your graphs.
Google Authenticator with OpenVPN for 2 factor auth
This post will describe how to get it working with Ubuntu 12.04. It should work with other versions along with other Linux distros. The only difference is the package names might change.
Install the packages
Run the following command
apt-get -y install openvpn libpam-google-authenticator
Setup OpenVPN
Place the cert key helps
mkdir /etc/openvpn/easy-rsa/
cp -R /usr/share/doc/openvpn/examples/easy-rsa/2.0/* /etc/openvpn/easy-rsa/
Then you need to edit the following file
/etc/openvpn/easy-rsa/vars
Scroll all the way down and find the following section and change it to your needs
export KEY_COUNTRY=US
export KEY_PROVINCE=NY
export KEY_CITY=NewYork
export KEY_ORG=”Company VPN”
export KEY_EMAIL=”sysops@company.com”
Set the permissions
cd /etc/openvpn/easy-rsa/
sudo chown -R root:admin .
sudo chmod g+w .
Source the vars file to pull in needed environment variables
source ./vars
Run the scripts to build your keys
./clean-all
./build-dh
./pkitool –initca
./pkitool –server server
cd keys
openvpn –genkey –secret ta.key
sudo cp server.crt server.key ca.crt dh1024.pem ta.key ../../
Create the following file
/etc/openvpn/up.sh
With the contents of
#!/bin/sh
BR=$1
DEV=$2
MTU=$3/sbin/ip link set “$DEV” up promisc on mtu “$MTU”
/sbin/brctl addif $BR $DEV
Then create another file called
/etc/openvpn/down.sh
With the contents of
#!/bin/sh
BR=$1
DEV=$2/sbin/brctl delif $BR $DEV
/sbin/ip link set “$DEV” down
Now set permissions on this files
chmod +x /etc/openvpn/up.sh /etc/openvpn/down.sh
Then you want to add the following to /etc/sysctl.conf
net.ipv4.ip_forward = 1
That will set it on reboot but you want to set it now run the following
echo 1 > /proc/sys/net/ipv4/ip_forward
Now setup pam to work for openvpn. Create the following file
/etc/pam.d/openvpn
Then put the following in
auth requisite pam_google_authenticator.so forward_pass
auth required pam_unix.so use_first_pass
Now you need to edit your openvpn config. I called mine server.conf in /etc/openvpn and you want to add the following
plugin /usr/lib/openvpn/openvpn-auth-pam.so openvpn
Now once openvpn is started you can run the following as the user you are setting up VPN for. They will need a shell account and they can do this themselves if needed. So run the following command
google-authenticator
Then choose the following options in this order.
Do you want authentication tokens to be time-based (y/n) y
Do you want me to update your “/home/bla/.google_authenticator” file (y/n) yDo you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) yBy default, tokens are good for 30 seconds and in order to compensate for
possible time-skew between the client and the server, we allow an extra
token before and after the current time. If you experience problems with poor
time synchronization, you can increase the window from its default
size of 1:30min to about 4min. Do you want to do so (y/n) yIf the computer that you are logging into isn’t hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting (y/n) y
You notice this command might show a QR code at the top which you can download the Google Authenticator app on your phone to scan that code and it will setup your account automatically. If it doesn’t show a QR code it will show a link that will display the code.
You can now run openvpn and connect and the username is your shell user and if you set the password to test123 and google gives you a code of 847324, your password would be test123847324
Simple script to selectively remove emails from postfix’s queue
If you send out a lot of emails, the queue in postfix might be full of junk emails from people putting like bla@example.net as their email address. Now there could be other valid emails in there that you don’t want to remove due to their mail server down and postfix keeps trying for a set amount of time to re-send that email. So below is a simple script that you have to run as root that you can enter a search string as a paramater to remove emails from the queue
Nagios check for monit
Here is a simple nagios check I just created to check the monitor status for monit. The background is as simple as this.. If you have a service that is flapping and monit is set to timeout after a number of failed attempts to start the service, it will un-monitor the service. Without m/monit running, you might never notice it is set as un-monitored. So I created a little python script to check for this
Mapping /proc/meminfo to output of free command
So an example output of free is
total used free shared buffers cached
Mem: 12333980 12151544 182436 0 233128 11197680
-/+ buffers/cache: 720820 11613160
Swap: 487416 3536 483880
And /proc/meminfo
MemTotal: 12333980 kB
MemFree: 182436 kB
Buffers: 233128 kB
Cached: 11197680 kB
SwapCached: 996 kB
Active: 7296040 kB
Inactive: 4231216 kB
Active(anon): 73848 kB
Inactive(anon): 22892 kB
Active(file): 7222192 kB
Inactive(file): 4208324 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 487416 kB
SwapFree: 483880 kB
Dirty: 268 kB
Writeback: 0 kB
AnonPages: 95640 kB
Mapped: 7686976 kB
Shmem: 292 kB
Slab: 346296 kB
SReclaimable: 335352 kB
SUnreclaim: 10944 kB
KernelStack: 1920 kB
PageTables: 23844 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 6654404 kB
Committed_AS: 613716 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 309052 kB
VmallocChunk: 34359422748 kB
HardwareCorrupted: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 10240 kB
DirectMap2M: 12572672 kB
I’ve done my best to match up the two outputs via colors. Below you will find the math used if there is any.
Total Memory
No math needed.. follow the colors
Used Memory
So for this we want to find the math used to get the used memory on the +/- buffers line. This is the true RAM used by the system.
So this math is based on output of the cat /proc/meminfo
MemTotal - (Buffers + Cached + MemFree)
So our example would be
12333980 - (182352 + 233128 + 11197680) = 720820
Free Memory
So for this we want to find the math used to get the free memory on the +/- buffers line. This is the true RAM that can be used by applications that request it. The operating system will remove data from here to give to applications on demand.
So this math is based on output of the cat /proc/meminfo
Cached + Buffers + MemFree
So our example would be
182352 + 233128 + 11197680 = 11613160
Total Swap
No math needed.. follow the colors
Used Swap
So to find out what free is outputting is pretty simple just do the math from the meminfo output
SwapTotal - SwapFree
So that would look like
487416 - 483880 = 3536
Free Swap
No math needed.. follow the colors
Varnish ACL with X-Forwarded-For Header
So I did a setup like this once
nginx -> varnish -> backend apaches
I did the nginx in front of varnish to handle SSL termination since varnish doesn’t do SSL. So the issue is you can do this for subnet checking in your varnish config
acl vpn {
"192.168.0.0"/16;
}
sub vcl_recv {
if (client.ip ~ vpn) {
# something here
}
return(pass);
}
So the issue with this is varnish thinks the client.ip is 127.0.0.1 which is correct since the connection is coming from nginx. If varnish was out in front of nginx we wouldn’t have this problem and the example above would just work. So you might be thinking why not just replace client.ip with something like req.http.x-forwarded-for and be done with it all. Well that is a string in varnish and client.ip is an object I believe so you can’t do that. So we have to do some C hacking in the config to get around this.
I found the following example a bit ago on another blog in the comments and if I remember I’ll give credit.
So we need to add the following to make it work
C{
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
}C
acl vpn {
"192.168.0.0"/16;
}
sub vcl_recv {
C{
//
// This is a hack from Igor Gariev (gariev hotmail com):
// Copy IP address from "X-Forwarded-For" header
// into Varnish's client_ip structure.
// This works with Varnish 3.0.1; test with other versions
//
// Trusted "X-Forwarded-For" header is a must!
// No commas are allowed. If your load balancer something other
// than a single IP, then use a regsub() to fix it.
//
struct sockaddr_storage *client_ip_ss = VRT_r_client_ip(sp);
struct sockaddr_in *client_ip_si = (struct sockaddr_in *) client_ip_ss;
struct in_addr *client_ip_ia = &(client_ip_si->sin_addr);
char *xff_ip = VRT_GetHdr(sp, HDR_REQ, "\020X-Forwarded-For:");
if (xff_ip != NULL) {
// Copy the ip address into the struct's sin_addr.
inet_pton(AF_INET, xff_ip, client_ip_ia);
}
}C
if (client.ip ~ vpn) {
# do something here
}
return(pass);
}
Now client.ip is set with the value of x-forwarded-for
Postfix ignore catchall relayhost
Postfix has an option where you can setup a relayhost to send all mail to another mail server. It looks something like
relayhost = [mail.domain.com]:25
So that will send all mail being sent out from the server to mail.domain.com on port 25. So what happens if you want to send mail that is sent to company.com out that server and not through another relay. You would do the following in main.cf
transport_maps = hash:/etc/postfix/transport
Then your /etc/postfix/transport would look something like
company.com :
* smtp:[mail.domain.com]:25
Then you want to run
postmap /etc/postfix/transport
Then reload postfix
service postfix reload
Now all mail for company.com will send out that server while all other mail will go through mail.domain.com:25
ps aux with line wrap
File this under you learn something new every day.
Ever do a ps aux only to get something like this to happen?
xymon 26931 0.0 0.0 38944 1396 ? S 05:44 0:00 sh -c vmstat 300 2 1>/usr/lib64/xymon/client/tmp/hob
So the output of ps aux gets cut off when it hits the end of your terminal. And you have to expand your width a lot to see it. It always bothered me till I decided to read the man page.
Now I learned you can do
ps aux --width 1000
That will line wrap your output but cut the output at 1000 characters. You can also pass w’s into the command like
ps auxww
That will ignore your terminals width settings
So now we can add the following in our .bashrc or for system wide /etc/profile so we never have to remember to add a ww or –width again
alias ps='ps ww'
So that alias means you can type ps aux and it will be like your typed ps auxww