Last active
September 10, 2022 21:48
-
-
Save mkorthof/e02838ef68ca33ad3bad19d6c644749e to your computer and use it in GitHub Desktop.
Piped logger for Apache to use with OpenVPN port_share (logs real client ip)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# pslog.sh - Piped logger for Apache to use with OpenVPN + port sharing | |
# Replaces remote ip in logs with real client ip | |
# | |
# USAGE: ErrorLog "|/usr/local/bin/pslog.sh ${APACHE_LOG_DIR}/error.log" | |
# CustomLog "|/usr/local/bin/pslog.sh ${APACHE_LOG_DIR}/access.log" combined | |
# | |
# REQUIRES: openvpn server config "port-share 127.0.0.1 10443 portshare" | |
# where 'portshare' is journal dir for tmp files (e.g. /run/openvpn/portshare if chrooted) | |
# | |
test -n "$1" && test -w "$1" && logfile="$1" || exit 1 # check for writable log | |
journal_dir="/run/openvpn_as/portshare" | |
openvpn_log="/var/log/openvpnas.log" | |
ip_regex='s/(.*\[AF_INET\])?(([0-9]{1,3}\.){1}([0-9]{1,3}\.){2}[0-9]{1,3}(:[0-9]+)?) ?.*/\2/p' | |
test -d "$journal_dir" || \ | |
{ install -m 700 -o openvpn_as -g openvpn_as -d "$journal_dir"; } # create journal dir | |
# EXAMPLE: | |
# tmpfile /run/openvpn/portshare/[AF_INET]127.0.0.1:12345 "[AF_INET]12.34.56.78:54321" | |
# logfile 2020-01-01T17:00:58+0200 [stdout#info] [OVPN 0] OUT: '2020-01-01 17:00:58 TCP connection established with [AF_INET]123.45.67.89:54321' | |
while read -r stdin; do | |
unset to_saddr from_saddr to_ip from_ip | |
for i in "$journal_dir"/\[AF_INET\]*:*; do | |
# first try to get ip from journal dir files | |
to_saddr="$( echo "$i" | sed -nr "$ip_regex" 2>/dev/null )" && \ | |
{ to_ip="$( echo "$to_saddr" | cut -d: -f1 )" || to_ip=""; } | |
from_saddr="$( sed -nr "$ip_regex" "$i" 2>/dev/null )" && \ | |
{ from_ip="$( echo "$from_saddr" | cut -d: -f1 )" || from_ip=""; } | |
# fallback: if no src ip found, try tailing openvpn log | |
if [ "$to_ip" = "" ] && [ -z "$to_saddr" ] && [ -z "$from_saddr" ]; then | |
to_saddr="$( echo "$stdin" | sed -nr "$ip_regex" 2>/dev/null )" | |
to_ip="$( echo "$to_saddr" | cut -d: -f1 )" | |
line="$( tail -10 "$openvpn_log" | tac | grep -m 1 "TCP.*AF_INET" )" | |
from_saddr="$( echo "$line" | awk '{ print $(NF) }' | sed -nr "$ip_regex" 2>/dev/null )" | |
from_ip="$( echo "$from_saddr" | cut -d: -f1 )" | |
ts="$( echo "$line" | awk '{ print $1, $2 }' | cut -d+ -f1 )" | |
if [ -n "$to_saddr" ] && [ -n "$from_saddr" ]; then | |
ap_fmt="+%d/%b/%Y:%H:%M:%S" | |
ap_ts="$( date "$ap_fmt" -d"$ts" )" | |
ap_ts_1s_add="$( date "$ap_fmt" -d"$ts 1 second" )" | |
ap_ts_1s_ago="$( date "$ap_fmt" -d"$ts 1 second ago" )" | |
# replace ip only if timestamp is between -1s and +1s | |
if echo "$stdin" | grep -Eq "($ap_ts|$ap_ts_1s_add|$ap_ts_1s_ago)"; then | |
if [ "$to_saddr" != "$to_ip" ]; then | |
echo "$stdin" | sed -e "s/$to_saddr/$from_saddr/" -e "s/$to_ip/$from_ip/" >> "$logfile" | |
else | |
echo "$stdin" | sed -e "s/$to_ip/$from_ip/" >> "$logfile" | |
fi | |
fi | |
# no matching lines | |
else | |
echo "$stdin" >> "$logfile" | |
fi | |
# cant get ip but have socket address, write that to log instead | |
elif [ -n "$to_saddr" ] && [ -n "$from_saddr" ]; then | |
echo "$stdin" | sed -e "s/$to_saddr/$from_saddr/" -e "s/$to_ip/$from_ip/" >> "$logfile" | |
# no tmp file matches, write unchanged input to log | |
else | |
echo "$stdin" >> "$logfile" | |
fi | |
done | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment