Archive for the ‘ How tos ’ Category

How to fake or spoof x-forwarded-for header

The x-forwarded-for header is a way of identifying the IP address of the original client when a web server is sitting behind a proxy or load-balancer. The load-balancer does get the actual client IP as it directly sets up the TCP session with the load-balancer. But the x-forwarded-for address might contain a list of comma separated IP addresses in addition to the immediate client IP. It is these extra IPs that we can spoof and the procedure is similar to modifying any HTTP header such as user agent.

import requests
headers={'X-Forwarded-For':'1.1.1.1'}
r = requests.get('http://web.home.net/index.html', headers=headers)
if r.ok:
    print('Success.')

How the log likes like on an nginx access log –

1.1.1.1, 192.168.10.206 - - [19/Mar/2017:16:43:55 -0700] "GET /index.html HTTP/1.0" 200 1311 "-" "python-requests/2.2.1 CPython/2.7.6 Linux/3.13.0-121-generic"
1.1.1.1, 192.168.10.206 - - [19/Mar/2017:16:53:55 -0700] "GET /index.html HTTP/1.0" 200 1311 "-" "python-requests/2.2.1 CPython/2.7.6 Linux/3.13.0-121-generic"
1.1.1.1, 192.168.10.206 - - [19/Mar/2017:16:58:55 -0700] "GET /index.html HTTP/1.0" 200 1311 "-" "python-requests/2.2.1 CPython/2.7.6 Linux/3.13.0-121-generic"

The take away is not to trust any IPs in the x-forwarded-for list apart from the load balancer IP and the immediate client IP which made a direct call to the load balancer. If we trust our load balancer, we can also reliably identify the immediate client IP. The rest of the IPs in the x-forwarded-for list can be ignored.

References –

https://en.wikipedia.org/wiki/X-Forwarded-For

git – add local files to a git repository in local file system (bare git repo).

In this blow, I will show you how you can turn your local files into a github style repository. In my case I had files in `/etc/puppet` that I wanted to version control, but I wanted to push to a bare repository in the same machine or localhost. Here are the steps I followed –

Files to version control : /etc/puppet
Bare git repository that we will push changes in /etc/puppet : /var/lib/puppet/gitrepo/

1. Create a github style git repository in /var/lib/puppet/gitrepo

root@linubuvmb:/# mkdir -p /var/lib/puppet/gitrepo && cd /var/lib/puppet/gitrepo
root@linubuvmb:/var/lib/puppet/gitrepo# git --bare init
Initialized empty Git repository in /var/lib/puppet/gitrepo/

2. Initialize files as git repository

root@linubuvmb:/# cd /etc/puppet
root@linubuvmb:/etc/puppet# git init
Initialized empty Git repository in /etc/puppet/.git/
root@linubuvmb:/etc/puppet# git add .
root@linubuvmb:/etc/puppet# git commit -m 'First commit'
[master (root-commit) b71ef42] First commit
 50 files changed, 3913 insertions(+)
 create mode 100644 auth.conf
 create mode 100644 environments/example_env/README.environment
 create mode 100755 etckeeper-commit-post
 create mode 100755 etckeeper-commit-pre
 create mode 100644 fileserver.conf
 create mode 100644 manifests/base.pp
 create mode 100644 manifests/nodes.pp
 create mode 100644 manifests/site.pp
 create mode 100644 modules/apache/manifests/init.pp
...

3. Add bare repo as remote

root@linubuvmb:/etc/puppet# git remote add origin file:///var/lib/puppet/gitrepo/

4. Push to local git repository

root@linubuvmb:/etc/puppet# git push -u origin master
Counting objects: 84, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (70/70), done.
Writing objects: 100% (84/84), 129.33 KiB | 0 bytes/s, done.
Total 84 (delta 6), reused 0 (delta 0)
To file:///var/lib/puppet/gitrepo/
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.
root@linubuvmb:/etc/puppet# git status
On branch master
Your branch is up-to-date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   puppet.conf

no changes added to commit (use "git add" and/or "git commit -a")
root@linubuvmb:/etc/puppet# git commit -a
[master f57997d] test
 1 file changed, 1 deletion(-)
root@linubuvmb:/etc/puppet# git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working directory clean

Reference –

https://git-scm.com/documentation

List shared or dynamic libraries required by a program

In Linux, the

ldd

is used to find out the shared libraries or dependencies required by a program if it is a dynamic executable. ldd requires the full path to the executable as input.

For instance, the Linux ps command depends on the following shared or dynamic libraries –

[root@kauai rtc0]# ldd $(which ps)
	linux-vdso.so.1 =>  (0x00007ffeb6277000)
	libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003ef6200000)
	libproc-3.2.8.so => /lib64/libproc-3.2.8.so (0x0000003ef4e00000)
	libc.so.6 => /lib64/libc.so.6 (0x0000003ef4a00000)
	libdl.so.2 => /lib64/libdl.so.2 (0x0000003ef5600000)
	/lib64/ld-linux-x86-64.so.2 (0x0000003ef4600000)

You can also use the ldd command to find out if an executable has an expected dependencies. In this case, we expect that the htpasswd, login and sshd commands depend on the crypt library as they prompt a user for a password for authentication purposes –


[root@kauai rtc0]# ldd $(which htpasswd) |grep crypt
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f010c8ab000)

[root@kauai rtc0]# ldd $(which login) | grep crypt
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x0000003efd200000)

[root@kauai rtc0]# ldd $(which sshd) | grep crypt
	libcrypto.so.10 => /usr/lib64/libcrypto.so.10 (0x00007ffb0b1f2000)
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007ffb0a988000)
	libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007ffb0a015000)

References –

http://man7.org/linux/man-pages/man1/ldd.1.html

Getting date from Real time clock (RTC) without using the date command or any other Linux time related commands.

In Linux, the “Real Time Clock” tracks wall clock time and is battery backed so that it works even with system power off. The RTC has no concept of time zone or daylight saving, it defaults to UTC. One of the user interfaces that the Linux Kernel exposes is

 /sys/class/rtc/rtc{N} 

and we will use the files in that directory to directly read time related data from the RTC.

* Files –

[root@ns3 rtc0]# ls /sys/class/rtc/rtc0
date  dev  device  hctosys  max_user_freq  name  power  since_epoch  subsystem  time  uevent  wakealarm

* Date and time in UTC

[root@ns3 rtc0]# cat date
2015-01-19
[root@ns3 rtc0]# cat time
23:05:05

* The maximum interrupt rate an unprivileged user may request from this RTC.

# cat max_user_freq
64

* The name of the RTC corresponding to this sysfs directory

[root@ns3 rtc0]# cat name
rtc_cmos

* The number of seconds since the epoch according to the RTC

[root@ns3 rtc0]# cat since_epoch
1421708627

* Status information is reported through the pseudo-file /proc/driver/rtc

[root@ns3 rtc0]# cat /proc/driver/rtc
rtc_time        : 23:06:58
rtc_date        : 2015-01-19
alrm_time       : 01:00:02
alrm_date       : ****-**-**
alarm_IRQ       : no
alrm_pending    : no
24hr            : yes
periodic_IRQ    : no
update_IRQ      : no
HPET_emulated   : no
DST_enable      : no
periodic_freq   : 1024
batt_status     : okay

References –

Real Time Clock (RTC) Drivers for Linux

Nginx / Apache – log real client IP or x-forwarded-for address.

Web servers such as Nginx or Apache when configured as reverse proxy behind a load balancer, they log the IP address of the load balancer in the access logs as the source IP. For practical use cases, you will usually want to log the actual client IP addresses.

In this setup, Nginx is setup to mimic a load balancer (reverse proxy) with multiple Apache web servers as backend.

1. Nginx snippet configuration to set x_forwarded_for proxy header –


server {
  listen 80;
  listen 443 default ssl;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   .....
   }

2. Apache snippet Configuration to capture x_forwarded_for header in the access logs –


<VirtualHost *:443>
    ServerAdmin webmaster@home.net
    DocumentRoot /var/www/homenet
    ServerName todo.home.net
...
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" proxy
    SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
    CustomLog "logs/todo.home.net-ssl_access_log" combined env=!forwarded
    CustomLog "logs/todo.home.net-ssl_access_log" proxy env=forwarded
 </Virtual>

Before making the above custom changes , the logs showed the load balancer IP 192.168.10.162 only –

192.168.10.162 - - [19/Mar/2015:16:21:10 -0700] "GET /signup.php HTTP/1.0" 200 1237
192.168.10.162 - - [19/Mar/2015:16:21:11 -0700] "GET /login.php HTTP/1.0" 200 1715

After the change the client IP (192.168.10.105) was logged –

192.168.10.105 - - [19/Mar/2015:16:26:43 -0700] "GET / HTTP/1.0" 200 1311 "https://todo.home.net/login.php" "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:35.0) Gecko/20100101 Firefox/35.0"
192.168.10.105 - - [19/Mar/2015:16:26:44 -0700] "GET /signup.php HTTP/1.0" 200 1237 "https://todo.home.net/" "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:35.0) Gecko/20100101 Firefox/35.0"

References –

https://www.nginx.com/resources/wiki/start/topics/examples/likeapache/

Free SSL certificates with Let’s Encrypt certbot – tested in Ubuntu 14.04 with Apache 2.

It is nice to have a site with valid SSL certificates, your visitors will be happy when they see that green padlock. Unfortunately it generally costs time and money to setup SSL certificates. Most big businesses with buy SSL certificates from well know Certificate Authorities(CAs) such as VeriSign, Symantec or GlobalSign. If you run a personal blog though and you can still get free SSL certificates.

Benefits of certificates –

a. Search engines such as Google give preference to secure sites
b. Security reasons – encryption and extended validation.

Disadvantages –

a. Introduces latency or delay
b. Operational cost to setup/renew certificates

One of the most popular SSL certificate providers was StarCom or StarSSL, until Google recently stopped trusting the certificates issues by this CA in Google Chrome. In the blog post, Google says –‘Google has determined that two CAs, WoSign and StartCom, have not maintained the high standards expected of CAs and will no longer be trusted by Google Chrome, in accordance with our Root Certificate Policy. ‘

So what is the alternative? Once my site was blocked by Chrome with a cert warning – ERR_CERT_AUTHORITY_INVALID – I did a research on new options and I can across “Let us encrypt”. And it was way better than StartSSL as it was easy to generate and renew certificates. Every thing was automated. No more certificate creation and renewal hassle.

Here are the steps I followed to get new certificates for my site –

1. Install certbot

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-apache

2. Get SSL certificates and modify Apache configuration automagically with certbot!!

root@localhost:~# certbot --apache

Interactive session –

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):notshowingmyemail@example.com

-------------------------------------------------------------------------------
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree
in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel: A

-------------------------------------------------------------------------------
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o: Y

Here, certbot automatically detects my domains –

Which names would you like to activate HTTPS for?
-------------------------------------------------------------------------------
1: danasmera.com
2: www.danasmera.com
3: linuxfreelancer.com
4: www.linuxfreelancer.com
-------------------------------------------------------------------------------
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):1,2,3,4

Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for danasmera.com
tls-sni-01 challenge for www.danasmera.com
tls-sni-01 challenge for linuxfreelancer.com
tls-sni-01 challenge for www.linuxfreelancer.com
Waiting for verification...
Cleaning up challenges
Deploying Certificate for danasmera.com to VirtualHost /etc/apache2/sites-available/danasmera-ssl
Deploying Certificate for www.danasmera.com to VirtualHost /etc/apache2/sites-available/danasmera-ssl
Deploying Certificate for linuxfreelancer.com to VirtualHost /etc/apache2/sites-available/linuxfreelancer-ssl
Deploying Certificate for www.linuxfreelancer.com to VirtualHost /etc/apache2/sites-available/linuxfreelancer-ssl

Please choose whether HTTPS access is required or optional.
-------------------------------------------------------------------------------
1: Easy - Allow both HTTP and HTTPS access to these sites
2: Secure - Make all requests redirect to secure HTTPS access
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1

-------------------------------------------------------------------------------
Congratulations! You have successfully enabled https://danasmera.com,
https://www.danasmera.com, https://linuxfreelancer.com, and
https://www.linuxfreelancer.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=danasmera.com
https://www.ssllabs.com/ssltest/analyze.html?d=www.danasmera.com
https://www.ssllabs.com/ssltest/analyze.html?d=linuxfreelancer.com
https://www.ssllabs.com/ssltest/analyze.html?d=www.linuxfreelancer.com
-------------------------------------------------------------------------------

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/danasmera.com/fullchain.pem. Your cert will
expire on 2017-09-08. To obtain a new or tweaked version of this
certificate in the future, simply run certbot again with the
"certonly" option. To non-interactively renew *all* of your
certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

Just making sure my apache configuration is valid after certbot modified it –

root@localhost:~# apache2ctl -t
Syntax OK

certbot will create a ‘/etc/letsencrypt/live/’ directory and dump the SSL certificate, private key and cert chain in that directory –

SSLCertificateFile /etc/letsencrypt/live/danasmera.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/danasmera.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/danasmera.com/chain.pem

Certbot created a multidomain SSL certiticate for 90 days, and a renewal cron job was added to my server so that I don’t have to do manual renewals –

root@localhost:~# cat /etc/cron.d/certbot
# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc.  Renewal will only occur if expiration
# is within 30 days.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew

References –

https://certbot.eff.org/all-instructions/#ubuntu-14-04-trusty-apache
https://security.googleblog.com/2016/10/distrusting-wosign-and-startcom.html