We are attempting to set up Apache Mod Evasion to prevent future DOS attacks on one of our servers. Everything seems to be working well outside of email notifications. The stack is running PHP 7.1 and Apache2.4 on Ubuntu Server 16.04.
Email works fine via a test command:
sudo su - www-data -s /bin/bash -c 'echo "this is the body" | mail -s "Subject" webdev#domain.edu webdev#domain.edu'
Here is the mod evasion.conf:
<IfModule mod_evasive20.c>
DOSHashTableSize 3097
DOSPageCount 1
DOSSiteCount 1
DOSPageInterval 10
DOSSiteInterval 10
DOSBlockingPeriod 10
DOSEmailNotify root
#DOSSystemCommand "su - someuser -c '/sbin/... %s ...'"
DOSLogDir "/var/log/mod_evasive"
</IfModule>
Here is the ssmtp.conf file:
root=webdev#domain.edu
FromLineOverride=YES
Debug=YES
UseSTARTTLS=YES
UseTLS=YES
mailhub=email-smtp.us-east-1.amazonaws.com:465
AuthUser=#######
AuthPass=#######
AuthMethod=LOGIN
Here is the revaliases file:
root:noreply#domain.edu:email-smtp.us-east-1.amazonaws.com:25
www-data:noreply#domain.edu:email-smtp.us-east-1.amazonaws.com:25
mod_evasive has a hard-coded command of the mailer invocation, defined as MAILER inside the source-code and also mentioned in e.g. this bug report.
#define MAILER "/bin/mail %s"
%s is substituted by the value of directive DOSEmailNotify when sending mails. However, nowadays on most systems /bin/main is not used and you might want to use sendmail instead. What you could do, is to create a wrapper script as /bin/mail (assumed that this binary does not exist at all or is not used).
#!/bin/bash
if [ "$1" != "" ]
then
/usr/sbin/sendmail -t "$1"
fi
Adjust the path to your sendmail binary and finally make the script executable using chmod 0755 /bin/mail.
Related
I installed older Codeception 2.5 (because of module for PHP framework Yii1) like this:
composer require codeception/codeception:2.5.*
And then executed:
php vendor/bin/codecept run unit --coverage-html
And nothing happened. I can only see following code. I discovered that all 3 files (carbon, codecept, phpunit) in folder vendor/bin contain only this instead of PHP code:
#!/usr/bin/env sh
dir=$(cd "${0%[/\\]*}" > /dev/null; cd '../codeception/codeception' && pwd)
if [ -d /proc/cygdrive ]; then
case $(which php) in
$(readlink -n /proc/cygdrive)/*)
# We are in Cygwin using Windows php, so the path must be translated
dir=$(cygpath -m "$dir");
;;
esac
fi
"${dir}/codecept" "$#"
Why is that? I am using Ubuntu 16 in Vagrant (CognacBox image). If I use XAMPP and Windows 10 it works correctly. I used Composer v1 and v2. Both with the same problem.
This question already has answers here:
Apache 2.4.x ip blacklist
(2 answers)
Closed 2 years ago.
Hello I'd like to permenently ban anything requesting the directory "/backups/" now how can I do that using a PHP script or mod_security?
I want to do this in a similar manner as iptables does this if possible.
I figured out how to do this on my own.
create a script in /bin called "blockip" containing the following
if [ -z "$1" ]
then
echo "No argument supplied"
exit 1
fi
echo "Blocking IP address $1"
iptables -A INPUT -s $1 -j DROP
then
chmod +x /bin/blockip
and now run
sudo visudo
add this:
nobody ALL = NOPASSWD: /your/script
make sure it is chmod 755
and add this code to index.php in the directory.
exec("sudo blockip ".escapeshellcmd($_SERVER['REMOTE_ADDR']));
Httpd processes use a non-default configuration file if they are run with the -f flag.
For example
/home/myuser/apache/httpd-2.4.8/bin/httpd -f /confFiles/apache/2.4.8/apache.conf -k start
will use this configuration file: /confFiles/apache/2.4.8/apache.conf
I need to get this location and would rather not have to check for possible -f flags used to start httpd.
The answer here says to run /path/to/httpd -V and concatenate
-D SERVER_CONFIG_FILE="conf/httpd.conf"
with
-D HTTPD_ROOT="/etc/httpd"
to get the final path to the config file.
However, this path will not be the correct one if the -f flag is used to start the httpd process.
Is there a command that can get the config file that is actually being used by the process?
The answer you refer to mentions the paths httpd was compiled with, but as you say those can be manually changed with parameters.
The simple way to check is the command line, if process is called "httpd" (standard name), a simple ps will reveal the config file being used:
ps auxw | grep httpd
Or querying the server if server has mod_info loaded, in command line or with your favourite browser:
curl "http://yourserver.example.com/server-info?server" | grep -i "config file"
Note: mod_info should not be publicaly available for everyone to see.
I am creating a restricted user without shell for port forwarding only and I need to execute a script on login via pubkey, even if the user is connected via ssh -N user#host which doesn't asks SSH server for a shell.
The script should warn admin on connections authenticated with pubkey, so the user connecting shouldn't be able to skip the execution of the script (e.g., by connecting with ssh -N).
I have tried to no avail:
Setting the command at /etc/ssh/sshrc.
Using command="COMMAND" in .ssh/authorized_keys (man authorized_keys)
Setting up a script with the command as user's shell. (chsh -s /sbin/myscript.sh USERNAME)
Matching user in /etc/ssh/sshd_config like:
Match User MYUSERNAME
ForceCommand "/sbin/myscript.sh"
All work when user asks for shell, but if logged only for port forwarding and no shell (ssh -N) it doesn't work.
The ForceCommand option runs without a PTY unless the client requests one. As a result, you don't actually have a shell to execute scripts the way you might expect. In addition, the OpenSSH SSHD_CONFIG(5) man page clearly says:
The command is invoked by using the user's login shell with the -c option.
That means that if you've disabled the user's login shell, or set it to something like /bin/false, then ForceCommand can't work. Assuming that:
the user has a sensible shell defined,
that your target script is executable, and
that your script has an appropriate shebang line
then the following should work in your global sshd_config file once properly modified with the proper username and fully-qualified pathname to your custom script:
Match User foo
ForceCommand /path/to/script.sh
If you only need to run a script you can rely on pam_exec.
Basically you reference the script you need to run in the /etc/pam.d/sshd configuration:
session optional pam_exec.so seteuid /path/to/script.sh
After some testing you may want to change optional to required.
Please refer to this answer "bash - How do I set up an email alert when a ssh login is successful? - Ask Ubuntu" for a similar request.
Indeed in the script only a limited subset on the environment variables is available:
LANGUAGE=en_US.UTF-8
PAM_USER=bitnami
PAM_RHOST=192.168.1.17
PAM_TYPE=open_session
PAM_SERVICE=sshd
PAM_TTY=ssh
LANG=en_US.UTF-8
LC_ALL=en_US.UTF-8
PWD=/
If you want to get the user info from authorized_keys this script could be helpful:
#!/bin/bash
# Get user from authorized_keys
# pam_exec_login.sh
# * [ssh - What is the SHA256 that comes on the sshd entry in auth.log? - Server Fault](https://serverfault.com/questions/888281/what-is-the-sha256-that-comes-on-the-sshd-entry-in-auth-log)
# * [bash - How to get all fingerprints for .ssh/authorized_keys(2) file - Server Fault](https://serverfault.com/questions/413231/how-to-get-all-fingerprints-for-ssh-authorized-keys2-file)
# Setup log
b=$(basename $0| cut -d. -f1)
log="/tmp/${b}.log"
function timeStamp () {
echo "$(date '+%b %d %H:%M:%S') ${HOSTNAME} $b[$$]:"
}
# Check if opening a remote session with sshd
if [ "${PAM_TYPE}" != "open_session" ] || [ $PAM_SERVICE != "sshd" ] || [ $PAM_RHOST == "::1" ]; then
exit $PAM_SUCCESS
fi
# Get info from auth.log
authLogLine=$(journalctl -u ssh.service |tail -100 |grep "sshd\[${PPID}\]" |grep "${PAM_RHOST}")
echo ${authLogLine} >> ${log}
PAM_USER_PORT=$(echo ${authLogLine}| sed -r 's/.*port (.*) ssh2.*/\1/')
PAM_USER_SHA256=$(echo ${authLogLine}| sed -r 's/.*SHA256:(.*)/\1/')
# Get details from .ssh/authorized_keys
authFile="/home/${PAM_USER}/.ssh/authorized_keys"
PAM_USER_authorized_keys=""
while read l; do
if [[ -n "$l" && "${l###}" = "$l" ]]; then
authFileSHA256=$(ssh-keygen -l -f <(echo "$l"))
if [[ "${authFileSHA256}" == *"${PAM_USER_SHA256}"* ]]; then
PAM_USER_authorized_keys=$(echo ${authFileSHA256}| cut -d" " -f3)
break
fi
fi
done < ${authFile}
if [[ -n ${PAM_USER_authorized_keys} ]]
then
echo "$(timeStamp) Local user: ${PAM_USER}, authorized_keys user: ${PAM_USER_authorized_keys}" >> ${log}
else
echo "$(timeStamp) WARNING: no matching user in authorized_keys" >> ${log}
fi
I am the author of the OP; I came to the conclusion that what I need to achieve is not possible using SSH only to the date (OpenSSH_6.9p1 Ubuntu-2, OpenSSL 1.0.2d 9 Jul 2015), but I found a great piece of software that uses encrypted SPAuthentication to open SSH port and it's new version (to the date of this post, it's GitHub master branch) has a feature to execute a command always that a user authorizates successfully.
FWKNOP - Encrypted Single Packet Authorization
FWKNOP set iptables rules that allow access to given ports upon a single packet encrypted which is sent via UDP. Then after authorization it allow access for the authorized user for a given time, for example 30 seconds, closing the port after this, leaving the connection open.
1. To install on an Ubuntu linux:
The current version (2.6.0-2.1build1) on Ubuntu repositories to the date still doesn't allow command execution on successful SPA; (please use 2.6.8 from GitHub instead)
On client machine:
sudo apt-get install fwknop-client
On server side:
sudo apt-get install fwknop-server
Here is a tutorial on how to setup the client and server machines
https://help.ubuntu.com/community/SinglePacketAuthorization
Then, after it is set up, on server side:
Edit /etc/default/fwknop-server
Change the line START_DAEMON="no" to START_DAEMON="yes"
Then run:
sudo service fwknop-server stop
sudo service fwknop-server start
2. Warning admin on successful SPA (email, pushover script etc)
So, as stated above the current version present in Ubuntu repositories (2.6.0-2.1build1) cannot execute command on successful SPA. If you need this feature as of the OP, but it will be released at fwknop version (2.6.8), as can it is stated here:
https://github.com/mrash/fwknop/issues/172
So if you need to use it right now you can build from github branch master which have the CMD_CYCLE_OPEN option.
3. More resources on fwknop
https://help.ubuntu.com/community/SinglePacketAuthorization
https://github.com/mrash/fwknop/ (project on GitHub)
http://www.cipherdyne.org/fwknop/ (project site)
https://www.digitalocean.com/community/tutorials/how-to-use-fwknop-to-enable-single-packet-authentication-on-ubuntu-12-04 (tutorial on DO's community)
I am the author of the OP. Also, you can implement a simple logwatcher as the following written in python3, which keeps reading for a file and executes a command when line contains pattern.
logwatcher.python3
#!/usr/bin/env python3
# follow.py
#
# Follow a file like tail -f.
import sys
import os
import time
def follow(thefile):
thefile.seek(0,2)
while True:
line = thefile.readline()
if not line:
time.sleep(0.5)
continue
yield line
if __name__ == '__main__':
logfilename = sys.argv[1]
pattern_string = sys.argv[2]
command_to_execute = sys.argv[3]
print("Log filename is: {}".format(logfilename))
logfile = open(logfilename, "r")
loglines = follow(logfile)
for line in loglines:
if pattern_string in line:
os.system(command_to_execute)
Usage
Make the above script executable:
chmod +x logwatcher.python3
Add a cronjob to start it after reboot
crontab -e
Then write this line there and save it after this:
#reboot /home/YOURUSERNAME/logwatcher.python3 "/var/log/auth.log" "session opened for user" "/sbin/myscript.sh"
The first argument of this script is the log file to watch, and the second argument is the string for which to look in it. The third argument is the script to execute when the line is found in file.
It is best if you use something more reliable to start/restart the script in case it crashes.
In /usr/local/nagios/etc/nrpe.cfg I added a new command check_this_process to the already pre-defined ones:
command[check_users]=/usr/local/nagios/libexec/check_users -w 5 -c 10
command[check_load]=/usr/local/nagios/libexec/check_load -w 15,10,5 -c 30,25,20
command[check_hda1]=/usr/local/nagios/libexec/check_disk -w 20% -c 10% -p /dev/$
command[check_zombie_procs]=/usr/local/nagios/libexec/check_procs -w 5 -c 10 -s$
command[check_total_procs]=/usr/local/nagios/libexec/check_procs -w 150 -c 200
command[check_this_process]=/usr/local/nagios/libexec/check_procs -w 15 -c 20 -C name
This works:
define service{
use generic-service
host_name my_host
service_description CPU Load
check_command check_nrpe!check_load
}
This doesn't:
define service{
use local-service
host_name my_host
service_description cron
check_command check_nrpe!check_this_process
}
and returns: NRPE: Command 'check_this_process' not defined
The terminology used in the supplied docs is a little confusing, but I'll put it like this:
As written in Page 10 of https://assets.nagios.com/downloads/nagioscore/docs/nrpe/NRPE.pdf, you need to modify /usr/local/nagios/etc/commands.cfg on your Nagios server and add the following to define the check_nrpe command:
define command{
command_name check_nrpe
command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c $ARG1$
}
On your Nagios server, define your service definition as you've already done:
define service{
use local-service
host_name my_host
service_description cron
check_command check_nrpe!check_this_process
}
On your remote host to be monitored, the following is going to be different depending on whether you installed NRPE:
using the tarball and xinetd as in
https://assets.nagios.com/downloads/nagioscore/docs/nrpe/NRPE.pdf
or using a package manager like yum as in
http://sharadchhetri.com/2013/03/02/how-to-install-and-configure-nagios-nrpe-in-centos-and-red-hat/
If you used the tarball / xinetd method, your NRPE configuration file will likely be located at /usr/local/nagios/etc/nrpe.cfg on your remote-host-to-be-monitored. (To avoid typing that all the time, I'll just call it "my_host").
So, on my_host, modify /usr/local/nagios/etc/nrpe.cfg.
Add
command[check_this_process]=/usr/local/nagios/libexec/check_procs -w 15 -c 20 -C name
So that it looks like:
command[check_users]=/usr/local/nagios/libexec/check_users -w 5 -c 10
command[check_load]=/usr/local/nagios/libexec/check_load -w 15,10,5 -c 30,25,20
command[check_hda1]=/usr/local/nagios/libexec/check_disk -w 20% -c 10% -p /dev/$
command[check_zombie_procs]=/usr/local/nagios/libexec/check_procs -w 5 -c 10 -s$
command[check_total_procs]=/usr/local/nagios/libexec/check_procs -w 150 -c 200
command[check_this_process]=/usr/local/nagios/libexec/check_procs -w 15 -c 20 -C name
(Note: the above is assuming you have a process called name. If not, replace name with your real process name: i.e. crond)
Restart xinetd:
service xinetd restart
(NOTE: restarting xinted might not be necessary, but I don't use it so I'm a little fuzzy on this one.)
However, if you installed NRPE on my_host using a package manager like yum, your NRPE configuration file will likely be located at /etc/nagios/nrpe.cfg.
So, on my_host, modify /etc/nagios/nrpe.cfg.
Add
command[check_this_process]=/usr/local/nagios/libexec/check_procs -w 15 -c 20 -C name
So that it looks like:
command[check_users]=/usr/local/nagios/libexec/check_users -w 5 -c 10
command[check_load]=/usr/local/nagios/libexec/check_load -w 15,10,5 -c 30,25,20
command[check_hda1]=/usr/local/nagios/libexec/check_disk -w 20% -c 10% -p /dev/$
command[check_zombie_procs]=/usr/local/nagios/libexec/check_procs -w 5 -c 10 -s$
command[check_total_procs]=/usr/local/nagios/libexec/check_procs -w 150 -c 200
command[check_this_process]=/usr/local/nagios/libexec/check_procs -w 15 -c 20 -C name
Restart the nrpe service:
service nrpe restart
Back on your Nagios server, run a verification of your Nagios configuration settings:
nagios -v /usr/local/nagios/etc/nagios.cfg
Check the output for errors.
If there are no errors, restart Nagios:
service nagios restart
On your Nagios server you should have a check_nrpe utility installed somehwere as a result of installing the "check_nrpe plugin" on your Nagios server.
See pages 9 and 10 of: https://assets.nagios.com/downloads/nagioscore/docs/nrpe/NRPE.pdf
This check_nrpe utility will most likely be located at: /usr/local/nagios/libexec/check_nrpe
Using the host information for my_host manually test your NRPE connection from the Nagios server.
Execute the following:
/usr/local/nagios/libexec/check_nrpe -H <IP Address of my_host> -c check_this_process
If everything is setup correctly, you should get some output on the command line.
My trouble-shooting guide for 'NRPE: Command ... not found.' Ordered from most common to least common - in my environment.
Was the NRPE daemon restarted AFTER adding the new command? If it is a new command, then NRPE MUST be restarted.
Typos/spelling errors. Does the configured command name on the Nagios side, match that the one in the NRPE config?
Permissions issues. Does the USER that NRPE runs as, have READABLE and EXECUTABLE access to the actual command being ran? Did you test run the command, as the NRPE user? On that same system? TIP: Use the dash (-) when changing to the NRPE user on Linux (su - ...) so you import said users environment as well.
Path issues. Was the FULL PATH to the actual command put into the NRPE config file? Doing this will normally eliminate issues with PATHs, so don't do it any other way.
Bad commands. Does the actual command really execute? Or is it simply throwing an error and exiting? Do you have the correct version of (INSERT SOMETHING HERE) to run the command, installed on the remote system? You should be able to run any command defined in the nrpe.cfg from the command line, and all new commands should be checked BEFORE being added to the nrpe.cfg.
IF ALL THE ABOVE FAILS: Enable DEBUGGING in NRPE and check the log files (on the remote host). This is a bit of a drawn out process - described in the documentation - read it. It is important to disable DEBUGGING as soon as you get output that looks like it would be useful.
This checklist ASSUMES that you've done the needful things to the various Nagios and NRPE configs to get it working in the first place. Hopefully others will read this before posting yet another question as to why they are seeing this error.