Archive for the ‘ Miscellaneous ’ Category

curl – use variables to show response times and other parameters


curl is a tool to interact with a server for transferring data. Although it supports various protocols, it is most commonly used with HTTP/S. It is sort of a browser for CLI folks and a go to tool when writing scripts to interact with servers.


In addition to transferring data, how do we show request and response parameters with curl. The answer is using variables, the complete list of variables can be found here.

Example – use “time_total” to show the total time, in seconds, that the full operation lasted.

$ curl  -w %{time_total} https://www.gcplinux.com
1.149143

It is best to add the variables in a file and use curl to reference the file for better formatting. Here I have added several http request and response variables I am interested in, such as num_connects, size_download, size_header, time_namelookup, time_pretransfer etc.


daniel@hidmo:/tmp$ cat ccurl.txt 
      url_effective:  %{url_effective}\n
       content_type:  %{content_type}\n
          http_code:  %{http_code}\n
       http_version:  %{http_version}\n
       num_connects:  %{num_connects}\n
      num_redirects:  %{num_redirects}\n
          remote_ip:  %{remote_ip}\n
      size_download:  %{size_download}\n
        size_header:  %{size_header}\n
    time_namelookup:  %{time_namelookup}\n
       time_connect:  %{time_connect}\n
    time_appconnect:  %{time_appconnect}\n
   time_pretransfer:  %{time_pretransfer}\n
      time_redirect:  %{time_redirect}\n
 time_starttransfer:  %{time_starttransfer}\n
                    ----------\n
         time_total:  %{time_total}\n


daniel@hidmo:/tmp$ curl -H 'Cache-Control: no-cache' -L -w "@ccurl.txt" -o /dev/null -s https://www.gcplinux.com
      url_effective:  https://gcplinux.com/
       content_type:  text/html; charset=UTF-8
          http_code:  200
       http_version:  1.1
       num_connects:  2
      num_redirects:  1
          remote_ip:  162.247.79.246
      size_download:  71273
        size_header:  537
    time_namelookup:  0.008585
       time_connect:  0.082511
    time_appconnect:  0.264110
   time_pretransfer:  0.264293
      time_redirect:  1.287257
 time_starttransfer:  3.077526
                    ----------
         time_total:  3.177939

As far as time related parameters, listed below are the ones you will most likely use –

  • time_appconnect The time, in seconds, it took from the start until the SSL/SSH/etc connect/handshake to the remote host was completed. (Added in 7.19.0)
  • time_connect The time, in seconds, it took from the start until the TCP connect to the remote host (or proxy) was completed.
  • time_namelookup The time, in seconds, it took from the start until the name resolving was completed.
  • time_pretransfer The time, in seconds, it took from the start until the file transfer was just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved.
  • time_redirect The time, in seconds, it took for all redirection steps including name lookup, connect, pretransfer and transfer before the final transaction was started. time_redirect shows the complete execution time for multiple redirections. (Added in 7.12.3)
  • time_starttransfer The time, in seconds, it took from the start until the first byte was just about to be transferred. This includes time_pretransfer and also the time the server needed to calculate the result.
  • time_total The total time, in seconds, that the full operation lasted.

References –


https://curl.haxx.se/docs/manpage.html

https://stackoverflow.com/questions/18215389/how-do-i-measure-request-and-response-times-at-once-using-curl

Error when running tree command

The tree command is a popular utility which lists the contents of a directory in a tree format, and it also allows users to specify the display depth of the directory tree. After installing the tree package in ubuntu, and running the tree command – I was getting below error:

$ tree .
sed: read error on .: Is a directory

The error doesn’t look like it is coming from the tree package just installed, after some digging I figured out that the “tree” command in this case was an alias. I use the Bash-it framework for a collection of bash commands and scripts and Bash-it has its own set of aliases including one for tree –

$ type tree
tree is aliased to `find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g''

In order to run the actual tree command, I had to prefix it with “command” or “\” as below –

$ command tree .
.
??? chapter-one
??? readme

1 directory, 1 file

$ \tree .
.
??? chapter-one
??? readme

1 directory, 1 file

References –

http://manpages.ubuntu.com/manpages/trusty/man1/tree.1.html

https://github.com/Bash-it/bash-it

Linux – Cannot assign requested address


While running a performance test on a local web service, I encountered below error –

$ ab -n 600000 -c 10000 http://localhost:8080/test
...
Benchmarking localhost (be patient)

Test aborted after 10 failures

apr_socket_connect(): Cannot assign requested address (99)

Clearly the number of concurrent requests(-n) and concurrent connections(-c) is high. But would it be possible to tweak my system so that it can handle this? Apparently yes. Doing some reading no Ephemeral port range. For a typical TCP connection, a 4-tuple of source IP/port and destination IP/port is required. In our case, the source and destination IP is fixed (127.0.0.1) as well as the destination port (8080). How many source port range do we have?

$ cat /proc/sys/net/ipv4/ip_local_port_range 
32768	60999

$ echo $((60999-32768))
28231

By increasing this port range, the system will accept more concurrent connections. Run below command under root –

root@lindell:~# echo "16000 65535" > /proc/sys/net/ipv4/ip_local_port_range
root@lindell:~# cat /proc/sys/net/ipv4/ip_local_port_range
16000	65535

The performance test now runs successfully –


$ ab -n 600000 -c 10000 http://localhost:8080/test
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 60000 requests
Completed 120000 requests
Completed 180000 requests
Completed 240000 requests
Completed 300000 requests
Completed 360000 requests
Completed 420000 requests
Completed 480000 requests
Completed 540000 requests
Completed 600000 requests
Finished 600000 requests


Server Software:        
Server Hostname:        localhost
Server Port:            8080

Document Path:          /test
Document Length:        13 bytes

Concurrency Level:      10000
Time taken for tests:   122.307 seconds
Complete requests:      600000
Failed requests:        0
Total transferred:      78000000 bytes
HTML transferred:       7800000 bytes
Requests per second:    4905.69 [#/sec] (mean)
Time per request:       2038.449 [ms] (mean)
Time per request:       0.204 [ms] (mean, across all concurrent requests)
Transfer rate:          622.79 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      308  848 180.0    833    3955
Processing:   293 1175 198.5   1190    1967
Waiting:       88  882 210.3    946    1738
Total:        932 2023 208.9   2018    5146

Percentage of the requests served within a certain time (ms)
  50%   2018
  66%   2085
  75%   2115
  80%   2138
  90%   2216
  95%   2298
  98%   2411
  99%   2961
 100%   5146 (longest request)


$ netstat -talpn |grep '127.0.0.1:8080' |wc -l
34241


References –

https://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html

https://httpd.apache.org/docs/2.4/programs/ab.html

WordPress – block xml-rpc

How to disable or block XML-RPC in wordpress served by apache server.

Per the official documentation –
XML-RPC on WordPress is actually an API or “application program interface“. It gives developers who make mobile apps, desktop apps and other services the ability to talk to your WordPress site. The XML-RPC API that WordPress provides gives developers a way to write applications (for you) that can do many of the things that you can do when logged into WordPress via the web interface

Unfortunately XML-RPC has drawbacks too, to mention some –

  • DDoS via XML-RPC pingbacks
  • Brute force attacks via XML-RPC

While looking at the access logs of my web servers, there were so many xmlrpc.php calls that looked suspicious.

121.42.52.27 - - [18/Sep/2019:22:53:32 -0400] "POST /xmlrpc.php HTTP/1.1" 200 3831 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  808526
121.42.52.27 - - [18/Sep/2019:22:53:34 -0400] "POST /xmlrpc.php HTTP/1.1" 200 816 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  868119
121.42.52.27 - - [18/Sep/2019:22:53:35 -0400] "POST /xmlrpc.php HTTP/1.1" 200 816 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  866812
121.42.52.27 - - [18/Sep/2019:22:53:37 -0400] "POST /xmlrpc.php HTTP/1.1" 200 816 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  708040
121.42.52.27 - - [18/Sep/2019:22:53:46 -0400] "POST /xmlrpc.php HTTP/1.1" 200 816 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  715609
121.42.52.27 - - [18/Sep/2019:22:53:48 -0400] "POST /xmlrpc.php HTTP/1.1" 200 816 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  768145
121.42.52.27 - - [18/Sep/2019:22:53:49 -0400] "POST /xmlrpc.php HTTP/1.1" 200 816 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  862514
121.42.52.27 - - [18/Sep/2019:22:53:56 -0400] "POST /xmlrpc.php HTTP/1.1" 200 816 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  847106
121.42.52.27 - - [18/Sep/2019:22:53:58 -0400] "POST /xmlrpc.php HTTP/1.1" 200 816 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  891537
121.42.52.27 - - [18/Sep/2019:22:54:02 -0400] "POST /xmlrpc.php HTTP/1.1" 200 816 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  983415
121.42.52.27 - - [18/Sep/2019:22:54:04 -0400] "POST /xmlrpc.php HTTP/1.1" 200 816 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  879661

Searching the abuse IP database –
https://www.abuseipdb.com/check/121.42.52.27 – the remote client hitting my server has been reported several times. Time to block this IP. After some googling, I came across a way to block it with .htaccess. We can either completely block the xmlrpc.php for all external IPs or for a specific blacklisted IPs.

In my .htaccess file, I added below line to block all IPs –

<Files xmlrpc.php>
order deny,allow
deny from all
allow from 127.0.0.1
</Files>

We can also block a specific IP address which is showing suspicious activity from our access logs –

<Files xmlrpc.php>
Order Deny,Allow
Allow from all
Deny from 121.42.52.27
</Files>

Post reloading apache, we can see that the remote client is getting 403s

121.42.52.27 - - [18/Sep/2019:22:55:02 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  1310
 121.42.52.27 - - [18/Sep/2019:22:55:03 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  1645
 121.42.52.27 - - [18/Sep/2019:22:55:05 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  1352
 121.42.52.27 - - [18/Sep/2019:22:55:05 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  1208
 121.42.52.27 - - [18/Sep/2019:22:55:06 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  1177
 121.42.52.27 - - [18/Sep/2019:22:55:06 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  1633
 121.42.52.27 - - [18/Sep/2019:22:55:06 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  1568
 121.42.52.27 - - [18/Sep/2019:22:55:06 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  1398
 121.42.52.27 - - [18/Sep/2019:22:55:07 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  1262
 121.42.52.27 - - [18/Sep/2019:22:55:07 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  1917
 121.42.52.27 - - [18/Sep/2019:22:55:08 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  2074
 121.42.52.27 - - [18/Sep/2019:22:55:08 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  1286
 121.42.52.27 - - [18/Sep/2019:22:55:08 -0400] "POST /xmlrpc.php HTTP/1.1" 403 634 "-" "Apache-HttpClient/4.5.2 (Java/1.8.0_151)"  847

References –

https://kinsta.com/blog/wordpress-xml-rpc/

Make http request with telnet

How to make an HTTP request with telnet


One of the most frequent interview question for tech professionals, especially system administrators and developers is – “tell us what happens when you type a URL in a browser?”. Skipping the DNS resolution part, we can understand the client to server HTTP communication with telnet. The simplest case is a GET request to a path with a HOST header.As an example, let us make an http request to an AWS service which responds back with our public IP address –

$ telnet checkip.amazonaws.com 80
....
GET / HTTP/1.1
Host: checkip.amazonaws.com
....

Here is the full transaction –


daniel@hidmo:~$ telnet checkip.amazonaws.com 80
Trying 18.214.132.216...
Connected to checkip.us-east-1.prod.check-ip.aws.a2z.com.
Escape character is '^]'.
GET / HTTP/1.1
Host: checkip.amazonaws.com

HTTP/1.1 200 OK
Date: Sat, 14 Sep 2019 12:51:55 GMT
Server: lighttpd/1.4.41
Content-Length: 14
Connection: keep-alive

162.247.79.245
Connection closed by foreign host.

Notice how the server closes the connection after waiting for a few seconds, that is because the keep-alive is enabled on the server side as shown from the server response – “Connection: keep-alive“. With keep-alive we can make additional http calls with out going through the whole 3-way TCP handshake.

Disable keep-alive on client side

If for some reason, we want to close the connection on the client side immediately we can pass “Connection: Close” as part of the http header in the request.


References –

Telnet manpage

https://stackoverflow.com/questions/15772355/how-to-send-an-http-request-using-telnet

https://www.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive


In Linux, the find command is most commonly used to search files using different criteria such as file name, size and modified time. Did you know that you can search files using inode number as well? Here is how to do it?

With “ls” we can find the inode number –

$ ls -li /etc/hosts
1576843 -rw-r--r-- 1 root root 311 Jan 21  2017 /etc/hosts

Using “-inum” option of find command, we can locate the filename and its path by its inode number.

$ find /etc -type f -inum 1576843 2>/dev/null 
/etc/hosts

$ cat $(find /etc -type f -inum 1576843 2>/dev/null)
127.0.0.1	localhost
127.0.1.1	ubuntu

References

http://man7.org/linux/man-pages/man7/inode.7.html

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