Tinyproxy is a lightweight yet powerful open source HTTP proxy, which can be used as both forward (outgoing) and reverse (incoming) HTTP proxy. One of the great features is the use of filters, which can serve as a list of either allowed or blocked domains.
In order to properly monitor Tinyproxy (used as a Forward Proxy), there are a couple of things to look out for.
Let's start with the most important check: An actual HTTP check which goes through the forward proxy, making an outgoing HTTP connection to a destination.
Luckily the check_http monitoring plugin, which is part of the monitoring-plugins package on Debian and Ubuntu and part of the nagios-plugins package on RedHat and derivatives, allows the use of a proxy.
The trick here is to change the request method (-j parameter). Instead of using a more commonly used GET or POST method, use the CONNECT method here.
-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT, CONNECT:POST)
Set HTTP method.
The --help output of check_http should even show an actual example how to use check_http with a proxy:
CHECK SSL WEBSERVER CONTENT VIA PROXY USING HTTP 1.1 CONNECT:
check_http -I 192.168.100.35 -p 80 -u https://www.verisign.com/ -S -j CONNECT -H www.verisign.com
all these options are needed: -I <proxy> -p <proxy-port> -u <check-url> -S(sl) -j CONNECT -H <webserver>
To monitor my own blog through the Proxy, I can therefore use:
ck@linux ~ $ /usr/lib/nagios/plugins/check_http -I 127.0.0.1 -p 8888 -u https://www.claudiokuenzler.com/ -S -j CONNECT -H www.claudiokuenzler.com
HTTP OK: HTTP/1.1 200 OK - 34990 bytes in 0.063 second response time |time=0.062641s;;;0.000000;10.000000 size=34990B;;;0
In this situation Tinyproxy is listening on 127.0.0.1:8888.
Using check_http is helpful to add this automated check into a monitoring software, such as Nagios or Icinga.
As a (manual) alternative, curl can be used to quickly check whether or not the HTTP request works through the Proxy. From curl's man page:
-x, --proxy [protocol://]host[:port]
Use the specified proxy.
The proxy string can be specified with a protocol:// prefix. No protocol specified or http:// will be
treated as HTTP proxy. Use socks4://, socks4a://, socks5:// or socks5h:// to request a specific SOCKS
version to be used. (The protocol support was added in curl 7.21.7)
HTTPS proxy support via https:// protocol prefix was added in 7.52.0 for OpenSSL, GnuTLS and NSS.
In the following example I am using curl via the Tinyproxy (again, listening on 127.0.0.1:8888) and send a HEAD request (-I) to my own blog:
ck@linux ~ $ curl --proxy http://127.0.0.1:8888 https://www.claudiokuenzler.com -I
HTTP/1.0 200 Connection established
Proxy-agent: tinyproxy/1.10.0
HTTP/2 200
server: nginx
date: Thu, 15 Dec 2022 06:43:00 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
strict-transport-security: max-age=63072000
The Tinyproxy log file (default location is /var/log/tinyproxy/tinyproxy.log) contains important information about connections. It also shows whether or not a destination domains was blocked (filtered). The default log verbosity does not show a lot, only with a LogLevel set to at least NOTICE important log events can be seen.
ck@linux ~ $ grep ^LogLevel /etc/tinyproxy/tinyproxy.conf
LogLevel Info
If Tinyproxy is under a lot of pressure (lots of concurrent connections) there might be need to increase the number of concurrent Tinyproxy servers (child processes) or to increase the number of concurrent connections. Log entries such as "Waiting servers" or similar are such log events.
ck@linux ~ $ tail -f /var/log/tinyproxy/tinyproxy.log
NOTICE Dec 15 07:08:26 [3999474]: Waiting servers (21) exceeds MaxSpareServers (20). Killing child.
NOTICE Dec 15 07:08:26 [4021250]: Waiting servers (21) exceeds MaxSpareServers (20). Killing child.
NOTICE Dec 15 07:08:26 [4021615]: Waiting servers (21) exceeds MaxSpareServers (20). Killing child.
NOTICE Dec 15 07:08:31 [1608899]: Waiting servers (0) is less than MinSpareServers (5). Creating new child.
NOTICE Dec 15 07:08:36 [1608899]: Waiting servers (0) is less than MinSpareServers (5). Creating new child.
NOTICE Dec 15 07:08:41 [1608899]: Waiting servers (0) is less than MinSpareServers (5). Creating new child.
NOTICE Dec 15 07:08:46 [1608899]: Waiting servers (0) is less than MinSpareServers (5). Creating new child.
NOTICE Dec 15 07:08:51 [1608899]: Waiting servers (0) is less than MinSpareServers (5). Creating new child.
NOTICE Dec 15 07:08:51 [3998401]: Waiting servers (21) exceeds MaxSpareServers (20). Killing child.
NOTICE Dec 15 07:08:51 [4004268]: Waiting servers (21) exceeds MaxSpareServers (20). Killing child.
NOTICE Dec 15 07:08:51 [4021297]: Waiting servers (21) exceeds MaxSpareServers (20). Killing child.
NOTICE Dec 15 07:08:51 [4020932]: Waiting servers (21) exceeds MaxSpareServers (20). Killing child.
NOTICE Dec 15 07:08:51 [4022756]: Waiting servers (21) exceeds MaxSpareServers (20). Killing child.
NOTICE Dec 15 07:08:56 [1608899]: Waiting servers (0) is less than MinSpareServers (5). Creating new child.
NOTICE Dec 15 07:09:01 [1608899]: Waiting servers (0) is less than MinSpareServers (5). Creating new child.
NOTICE Dec 15 07:09:06 [1608899]: Waiting servers (0) is less than MinSpareServers (5). Creating new child.
NOTICE Dec 15 07:09:11 [1608899]: Waiting servers (0) is less than MinSpareServers (5). Creating new child.
NOTICE Dec 15 07:09:16 [1608899]: Waiting servers (0) is less than MinSpareServers (5). Creating new child.
NOTICE Dec 15 07:09:21 [1608899]: Waiting servers (0) is less than MinSpareServers (5). Creating new child.
NOTICE Dec 15 07:09:21 [4001896]: Waiting servers (21) exceeds MaxSpareServers (20). Killing child.
NOTICE Dec 15 07:09:21 [4002820]: Waiting servers (21) exceeds MaxSpareServers (20). Killing child.
NOTICE Dec 15 07:09:21 [4022676]: Waiting servers (21) exceeds MaxSpareServers (20). Killing child.
The reason could also be that a lot of HTTP request at this moment are timing out (slow destination website) and causing the servers to be "stale" until the Tinyproxy timeout (default 300s) is hit.
Tinyproxy also comes with its own statistics site. The configuration file gives a hint:
ck@linux ~ $ grep stats /etc/tinyproxy/tinyproxy.conf
# tinyproxy.stats.
StatHost "tinyproxy.stats"
StatFile "/usr/share/tinyproxy/stats.html"
The StatHost is an "internal fake DNS" which tells Tinyproxy to display an internal HTTP page containing live statistics. These stats contain:
The statistics can be retrieved by making a HTTP request to Tinyproxy (such as a web server) and request the domain configured in StatHost (default: tinyproxy.stats):
ck@linux ~ $ curl -H "Host: tinyproxy.stats" http://127.0.0.1:8888
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>tinyproxy version 1.10.0 run-time statistics</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css" media="screen">
<!--/*--><![CDATA[<!--*/
th, td
text-align: left;
padding: 0.5em;
border: 1px solid gray;
}
/*]]>*/-->
</style>
</head>
<body>
<h1>tinyproxy version 1.10.0 run-time statistics</h1>
<table>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>Number of open connections</td>
<td>1</td>
</tr>
<tr>
<td>Number of requests</td>
<td>191</td>
</tr>
<tr>
<td>Number of bad connections</td>
<td>2</td>
</tr>
<tr>
<td>Number of denied connections</td>
<td>2</td>
</tr>
<tr>
<td>Number of refused connections due to high load</td>
<td>0</td>
</tr>
</table>
<hr />
<p><em>Generated by <a href="https://tinyproxy.github.io/">tinyproxy</a> version 1.10.0.</em></p>
</body>
</html>
As the output shows, this is a HTML output containing tables and nicely formatted columns for the human eye. If you want to (automatically) parse this output, a JSON output would be more better.
But this HTML output can be modified. The template to be used can be set in the Tinyproxy config using the StatFile option. By copying and modifying the existing template, you can easily create a better parseable output, such as JSON. Note that in order to "trick Tinyproxy" the starting curly braces needs to be set twice (Tinyproxy uses curly braces to define the internal variables):
ck@linux ~ $ cat /usr/share/tinyproxy/stats-json.html
{{ "version":"{version}", "open":{opens}, "requests":{reqs}, "bad":{badconns}, "denied":{deniedconns}, "refused":{refusedconns} }
This new template (stats-json.html) can now be defined in the Tinyproxy config:
ck@linux ~ $ grep StatFile /etc/tinyproxy/tinyproxy.conf
# StatFile: The HTML file that gets sent when a request is made
StatFile "/usr/share/tinyproxy/stats-json.html"
And after another reload (/etc/init.d/tinyproxy reload works, systemctl reload tinyproxy doesn't on Debian Bullseye), the HTTP stats can be retrieved in JSON format:
ck@linux ~ $ curl -H "Host: tinyproxy.stats" http://127.0.0.1:8888
{ "version":"1.10.0", "open":1, "requests":263, "bad":2, "denied":2, "refused":0 }
And with a JSON parser this can also be displayed as "pretty":
ck@linux ~ $ curl -s -H "Host: tinyproxy.stats" http://127.0.0.1:8888 | jq
{
"version": "1.10.0",
"open": 1,
"requests": 267,
"bad": 2,
"denied": 2,
"refused": 0
}
An output like this can now also be added into a monitoring software, e.g. by using the check_json monitoring plugin or an alternative.
No comments yet.
AWS Android Ansible Apache Apple Atlassian BSD Backup Bash Bluecoat CMS Chef Cloud Coding Consul Containers CouchDB DB DNS Database Databases Docker ELK Elasticsearch Filebeat FreeBSD Galera Git GlusterFS Grafana Graphics HAProxy HTML Hacks Hardware Icinga Influx Internet Java KVM Kibana Kodi Kubernetes LVM LXC Linux Logstash Mac Macintosh Mail MariaDB Minio MongoDB Monitoring Multimedia MySQL NFS Nagios Network Nginx OSSEC OTRS Office OpenSearch PGSQL PHP Perl Personal PostgreSQL Postgres PowerDNS Proxmox Proxy Python Rancher Rant Redis Roundcube SSL Samba Seafile Security Shell SmartOS Solaris Surveillance Systemd TLS Tomcat Ubuntu Unix VMWare VMware Varnish Virtualization Windows Wireless Wordpress Wyse ZFS Zoneminder