1

Is there a way to log all outgoing requests of PHP to a log file?

I'm not looking for a way to debug a single script with tcpdump but to continuously log all PHP requests, so I can review them later - i.e., very similar to the web servers access.log but for all outgoing requests that are made from any PHP script on the server.

I want to do two things with this:

  1. Confirm if my website is secure/GDPR-compliant and no scripts try to "phone home".
  2. Our server is supposed to make one external request per day. I want to validate that those requests happen, and ideally also see the response code that was returned by the remote site.

1 Answer 1

1

If you don't want to use tcpdump, providing you are running GNU/Linux on your server, you can use iptables owner match target.

First you need to check under which user your scripts are executed. If you are running Apache/mod_php this will be the same as apache user (usually apache or httpd). If you are running nginx/fastcgi/etc these might have other process owner (suid). Anyways mostly always this will be separate user id (uid), or at least you can change your configuration that way. Once you know your php uid, you can do an iptable owner match with LOG target. Something like this:

iptables -I OUTPUT -o eth0 -m owner --uid-owner apache -j LOG --log-prefix "PHP-CONN: "

Make sure to change interface you the one looking on the Internet side (to avoid logging localhost dummy requests). By default the example above will log every packet, including TCP handshakes, etc. You can add additional iptables options for more filtering. For example adding state match to filter only NEW connections (with netfilter conntrack):

iptables -I OUTPUT -o eth0 -m owner --uid-owner apache -m state --state NEW -j LOG --log-prefix "PHP-CONN: "

Then all those requests from your process will be logged to a syslog facility (depending on your distro setup, those are usually logged to dmesg + /var/log/messages or /var/log/syslog). Those will look similar to this:

PHP-CONN: IN= OUT=eth0 SRC=192.168.9.235 DST=195.201.201.32 LEN=52 TOS=0x10 PREC=0x00 TTL=64 ID=37120 DF PROTO=TCP SPT=56812 DPT=80 WINDOW=501 RES=0x00 ACK FIN URGP=0
5
  • Thanks for the detailed answer. Unfortunately, this only logs the IP address but not the actual request... I'm not opposed to using tcpdump, I just thought it's not possible to use it in this case, as it seems to record binary package-data in the log file.
    – Philipp
    Jun 2, 2021 at 13:42
  • @Philipp I see, I didn't thought you need to capture actual packets. But you can still use iptables with NFLOG target for this with ulogd. Or tcpdump. But considering most of the traffic now are encrypted on TLS layer, you won't be able to see actual requests coming on HTTPS anyways. Besides your scripts can use other protocols aside from HTTP(S). There are more reliable approach but much more complex what was offered in general on the answer here: stackoverflow.com/questions/44855624/…
    – NStorm
    Jun 2, 2021 at 17:22
  • Oh, and another complex (but reliable) way would be to setup a transparent HTTP(S) proxy and redirect all the traffic for the iptables through it. That way you can catch all the requests on the casual access-like log and decrypt TLS traffic with tricks like Squid SSL Bump or nginx Man-in-the-Middle (MITM) Proxy.
    – NStorm
    Jun 2, 2021 at 17:27
  • Thanks for your input and pointing out those alternative solutions! It turns out to be more complex to get the data than I thought. I did hope that there is a more standardized and less technical way...
    – Philipp
    Jun 2, 2021 at 18:24
  • If you don't "trust" or have a complete control over PHP source there is no simple way for this. But a transparent proxy + TLS MitM might be not as complex as it might sound at the first. There are a lot of guides for Squid based solutions for this. Next you just have to apply my answer to redirect OUTGOING web-server connections to Squid port, instead of all FORWARD traffic (which guides usually assume).
    – NStorm
    Jun 2, 2021 at 19:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .