PDA

Bekijk Volledige Versie : Vreemd crontab/script-probleem



Richard Rasker
08/01/03, 22:20
Dag beste allemaal,

Ik heb een bash-scriptje gemaakt met de naam blockcheck, dat op basis va=
n=20
het error-log van mijn Apache-webserver een blocklist aanmaakt met daari=
n=20
hosts die op hinderlijke wijze mijn serverlogs vervuilen met Code Red- e=
n=20
Nimda-scans. Dit blokkeerscript start vervolgens het=20
iptables-firewall-script (init_firewall), dat naast de normale=20
firewall-configuratie opdrachten bevat om alle hosts in de blocklist=20
geheel te blokkeren, zodat ze niet meer honderden of soms duizenden kere=
n=20
achtereen in mijn logs opduiken.

Nu heb ik het volgende probleem: als ik blockcheck handmatig start (als =

root), werkt alles perfect. Als ik blockcheck echter via cron laat=20
starten, gebeurt er iets vreemds: het firewall-script wordt wel compleet=
=20
uitgevoerd, maar de firewall-configuratie bestaat na afloop *niet* uit d=
e=20
opgegeven policy, maar uit de default-policy - wat natuurlijk erg=20
ongewenst is.

Dit is in het kort wat er gebeurt:
- cron roept blockcheck aan via de root-crontab
- blockcheck roept init_firewall aan
- init_firewall wordt keurig gestart, maar installeert *niet* de gewenst=
e=20
chains

Er treden geen foutmeldingen op, en toen ik in init_firewall wat=20
opdrachten

echo [voorgangsbericht] >> controlebestand

had rondgestrooid, bleek dat init_firewall van begin tot einde was=20
uitgevoerd.

Als ik blockcheck zoals gezegd handmatig uitvoer, doet init_firewall het=
=20
wel zoals ik verwacht. Het enige verschil is dus opstarten vanaf de=20
opdrachtregel versus opstarten via cron.

Weet iemand wat ik fout doe? Vermoedelijk zie ik iets fundamenteels over=
=20
het hoofd, maar ondanks dat ik van alles over cron en crontab heb=20
nageplozen, zie ik niet waar het verkeerd gaat.

Alvast bedankt,

Richard Rasker


Voor wie de details wil zien, volgen hier de betreffende scripts en=20
andere informatie.

>>>>>>>>>>>>>>> De crontab-instelling: <<<<<<<<<<<<<<<

# crontab -l
10 0,6,12,18 * * * /usr/local/bin/blockcheck

>>>>>>>>>>>>>>> Het script blockcheck: <<<<<<<<<<<<<<<

# cat blockcheck
#!/bin/bash
#
# blockcheck v. 1.0
# 29-12-2002
# Auteur: R.E.Rasker - rasker@linetec.nl
# http://www.linetec.nl/
#
# Dit script kan automatisch grote vervuilers van bijvoorbeeld
# webserver-logbestanden identificeren, in een blocklist opslaan
# en via een iptables-firewall blokkeren. In de blocklist wordt
# tevens de datum opgeslagen waarop een host is toegevoegd, zodat
# deze na een bepaalde expire-tijd ook weer automatisch uit de
# blocklist verwijderd kan worden.
#
# Het firewall-script zelf moet de volgende code bevatten om de
# blocklist automatisch te verwerken; deze code moet natuurlijk
# voorafgaan aan regels die toegang verlenen:
#
# for i in `grep -v "^#" /usr/local/etc/blocklist.db | cut -d : -f 1`; d=
o
# iptables -A INPUT -i eth0 -s $i -j block
# done
#
#
# Variabelen en vaste waarden:
# ERRMIN geeft aan hoe vaak een bepaald verdacht IP-adres minimaal
# in het error-log moet voorkomen om automatisch geblokkeerd te worden.
# EXPIRE geeft aan na hoeveel tijd een IP-adres weer toegang krijgt
# (de honderdtallen geven de maanden aan - al werkt dit niet bijzonder
# nauwkeurig).
# ERRLOG geeft de locatie aan van het Apache error-log.
# BLOCKLIST geeft de locatie aan van de blocklist; let op dat deze
# locatie ook in het firewall-script wordt gebruikt (zie boven).
# FIREWALL geeft de locatie aan van het firewall-script.
# De variabele FIRESTART geeft aan of de firewall uiteindelijk
# opnieuw gestart moet worden.

ERRMIN=3D10
EXPIRE=3D100
ERRLOG=3D/var/log/httpd/error_log
BLOCKLIST=3D/usr/local/etc/blocklist.db
FIREWALL=3D/usr/local/bin/init_firewall
FIRESTART=3Dfalse

# Allereerst wordt de huidige datum bepaald.

DATENOW=3D`date +%y%m%d`

# Met de volgende opdracht wordt gezocht naar hosts die pogen requests
# uit te voeren voor Windows-systeembestanden (zoals bij Nimda) of
# buffer-overflows (zoals bij CodeRed).
# De genoemde worms zijn de grootste logvervuilers:

for i in `grep "winnt.*exe\|NNNNNNNNNNN" $ERRLOG | sed -e 's/^.*\[client=
=20
//g' -e 's/\].*$//g' | sort -u`; do

# Als een host al in de blocklist voorkomt, moet dit gesignaleerd worden=
:
=20
MATCH=3Dfalse
for j in `grep -v "^#" $BLOCKLIST | cut -d : -f 1`; do
if [ $i =3D $j ]; then
MATCH=3Dtrue
fi
done
=20
# Als een host niet in de blocklist voorkomt, kijk dan of deze minstens =

het
# opgegeven aantal keren in ERRLOG voorkomt; zo ja, voeg de host dan toe=

# aan de blocklist, samen met de datum, en signaleer dat de firewall=20
opnieuw
# gestart moet worden:
=20
if [ $MATCH =3D false ]; then
if [ `grep -c $i $ERRLOG` -gt $ERRMIN ]; then
echo $i":"$DATENOW >> $BLOCKLIST
FIRESTART=3Dtrue
fi
fi
done
=20
# Voor de automatische expire van hosts in de blocklist wordt alleen=20
gekeken
# naar de datum. Zodra een expired host wordt gevonden, wordt dit=20
gesignaleerd
# om de firewall te kunnen aanpassen. Hosts die niet expired zijn, komen=
=20
in een
# tijdelijk bestand terecht, dat na de for-lus BLOCKLIST vervangt.
# Met de eerste grep-opdracht worden eventuele commentaarregels behouden=
..
=20
grep "#" $BLOCKLIST > $BLOCKLIST.tmp
for HOST in `grep -v "^#" $BLOCKLIST`; do
BLOCKDATE=3D`echo $HOST | cut -d : -f 2`
if [ `expr $DATENOW - $BLOCKDATE` -gt $EXPIRE ]; then
FIRESTART=3Dtrue
else
echo $HOST >> $BLOCKLIST.tmp
fi
done
mv $BLOCKLIST.tmp $BLOCKLIST
=20
# Als hosts aan BLOCKLIST zijn toegevoegd dan wel uit BLOCKLIST zijn=20
verwijderd,
# wordt de firewall opnieuw gestart:
=20
if $FIRESTART =3D true; then
$FIREWALL
fi

>>>>>>>>>>>>>>> Het script init_firewall: <<<<<<<<<<<<<<<<

#!/bin/sh
# Breng firewall down

/etc/rc.d/init.d/iptables stop

# NAT

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# Maak de blocking-chain

iptables -N block
iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A block -j DROP

# Zet forward vanaf buiten dicht

iptables -A FORWARD -i eth0 -j block

# Blokkeer hosts die door blockcheck zijn herkend:

for i in `grep -v "^#" /usr/local/etc/blocklist.db | cut -d : -f 1`; do
iptables -A INPUT -i eth0 -s $i -j block
done

# Accepteer ICMP/Echo

iptables -A INPUT -i eth0 -p icmp -j ACCEPT

# Accepteer WWW/HTTP

iptables -A INPUT -i eth0 -p tcp --dport www -j ACCEPT
iptables -A INPUT -i eth0 -p udp --dport www -j ACCEPT

# Zet rest van de input vanaf buiten dicht

iptables -A INPUT -i eth0 -j block

# Firewall-configuratie opslaan

/sbin/service iptables save

>>>>>>>>>>>>>>> De foutieve iptables-policy na uitvoering vanuit cron:=20
<<<<<<<<<<<<<<<

# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

>>>>>>>>>>>>>>> De correcte iptables-policy: <<<<<<<<<<<<<<<
(de drie IP-adressen xxx.xxx.xxx.xxx staan voor geblokkeerde hosts)

# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
block all -- xxx.xxx.xxx.xxx anywhere
block all -- xxx.xxx.xxx.xxx anywhere
block all -- xxx.xxx.xxx.xxx anywhere
ACCEPT icmp -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere tcp dpt:http=

ACCEPT udp -- anywhere anywhere udp dpt:http=

block all -- anywhere anywhere

Chain FORWARD (policy ACCEPT)
target prot opt source destination
block all -- anywhere anywhere

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Chain block (5 references)
target prot opt source destination
ACCEPT all -- anywhere anywhere state=20
RELATED,ESTABLISHED
DROP all -- anywhere anywhere

Wimjan
09/01/03, 00:36
Richard Rasker schreef:
> Dag beste allemaal,
>
> Ik heb een bash-scriptje gemaakt met de naam blockcheck, dat op basis va=
> n=20
>
Geen idee wat die verdwaalde = en =20-tekens hier doen, maar het leest
wel lastig. Is dit in een instelling in jouw news-programma of ligt het
aan mijn lezer?

> het error-log van mijn Apache-webserver een blocklist aanmaakt met daari=
> n=20
> hosts die op hinderlijke wijze mijn serverlogs vervuilen met Code Red- e=
> n=20
> Nimda-scans. Dit blokkeerscript start vervolgens het=20
> iptables-firewall-script (init_firewall), dat naast de normale=20
> firewall-configuratie opdrachten bevat om alle hosts in de blocklist=20
> geheel te blokkeren, zodat ze niet meer honderden of soms duizenden kere=
> n=20
> achtereen in mijn logs opduiken.
>
> Nu heb ik het volgende probleem: als ik blockcheck handmatig start (als =
> root), werkt alles perfect. Als ik blockcheck echter via cron laat=20
> starten, gebeurt er iets vreemds: het firewall-script wordt wel compleet=
> =20
> uitgevoerd, maar de firewall-configuratie bestaat na afloop *niet* uit d=
> e=20
> opgegeven policy, maar uit de default-policy - wat natuurlijk erg=20
> ongewenst is.
>
Zou het zo kunnen zijn dat je scriptje in een cronjob niet als root
(maar bijvoorbeeld als nobody) naar je configuratiebestand schrijft en
dat je firewall geen bestanden van die gebruiker mag lezen? Kijk eens wie
de owner is van het door je scriptje gegenereerde configuratiebestand
kortom.

[knip uitgebreide info]


Groet,

Wimjan

--
Iemands e-mailadres kwijt? Probeer m'n meta e-mail zoeker eens op
<http://inventio.nl/metanamesearch/>

Richard Rasker
09/01/03, 08:59
Op 1/9/03, 12:36:09 AM, schreef news+@inventio.nl (Wimjan) over het them=
a=20
Re: Vreemd crontab/script-probleem:

> Richard Rasker schreef:
> > Dag beste allemaal,
> >
> > Ik heb een bash-scriptje gemaakt met de naam blockcheck, dat op basi=
s va=3D

> Geen idee wat die verdwaalde =3D en =3D20-tekens hier doen, maar het l=
eest
> wel lastig. Is dit in een instelling in jouw news-programma of ligt he=
t
> aan mijn lezer?

Ik zie dit af en toe vaker optreden, en het komt door de combinatie van =

mijn wat verouderde StarOffice 5.2-newsreader en jouw eigen programma. I=
k=20
meen dat het te maken had met een ontbrekend MIME-type in StarOffice,=20
waar voor zover ik weet niets aan te doen is (misschien toch maar es=20
overstappen op OpenOffice en een echte newsreader). Excuses voor het ong=
emak.

> > het error-log van mijn Apache-webserver een blocklist aanmaakt met d=
aarin
> > hosts die op hinderlijke wijze mijn serverlogs vervuilen met Code Re=
d- en
> > Nimda-scans. Dit blokkeerscript start vervolgens het
> > iptables-firewall-script (init_firewall), dat naast de normale
> > firewall-configuratie opdrachten bevat om alle hosts in de blocklist=

> > geheel te blokkeren, zodat ze niet meer honderden of soms duizenden =
keren
> > achtereen in mijn logs opduiken.
> >
> > Nu heb ik het volgende probleem: als ik blockcheck handmatig start (=
als
> > root), werkt alles perfect. Als ik blockcheck echter via cron laat
> > starten, gebeurt er iets vreemds: het firewall-script wordt wel comp=
leet
> > uitgevoerd, maar de firewall-configuratie bestaat na afloop *niet* u=
it de
> > opgegeven policy, maar uit de default-policy - wat natuurlijk erg
> > ongewenst is.
> >
> Zou het zo kunnen zijn dat je scriptje in een cronjob niet als root
> (maar bijvoorbeeld als nobody) naar je configuratiebestand schrijft en=

> dat je firewall geen bestanden van die gebruiker mag lezen? Kijk eens =
wie
> de owner is van het door je scriptje gegenereerde configuratiebestand
> kortom.

Dank voor je reactie, maar het is inmiddels duidelijk wat er gebeurt: de=
=20
opdracht iptables in het script init_firewall moet /sbin/iptables zijn -=
=20
PATH (waarin /sbin is opgenomen) werkt niet bij cronjobs, maar wel vanui=
t=20
de shell... Zoals ik al vermoedde een tamelijk domme fout van mijn kant =
-=20
en helemaal omdat ik verzuimd heb de root-mail te lezen, waaruit e.e.a. =

al snel duidelijk bleek (ik had alleen in de verschillende logbestanden =

gekeken).

Richard Rasker

Jan Pieter
10/01/03, 09:56
Richard Rasker wrote:

> en helemaal omdat ik verzuimd heb de root-mail te lezen, waaruit e.e.a.
> al snel duidelijk bleek

Misschien handig om root mail te forwarden? In /etc/aliases:
root: user

Zou je dat scriptje eens kunnen posten/mailen/online zetten?


Jan Pieter.

Koos Pol
10/01/03, 10:20
Jan Pieter wrote (Friday 10 January 2003 09:56):

> Richard Rasker wrote:
>
>> en helemaal omdat ik verzuimd heb de root-mail te lezen, waaruit e.e.a.
>> al snel duidelijk bleek
>
> Misschien handig om root mail te forwarden? In /etc/aliases:
> root: user


Het is niet alleen handig, het is zelfs gebruikelijk/standaard/verplicht.
Nou ja, vooruit het is niet verplicht. Een systeem zonder root alias is nog
niet af:

1. Je bent zelden als root aangelogd terwijl je wel *altijd* systeembeheer
verantwoordelijkheid hebt. Ook als je niet bent aangelogd.

2. Op sommige systemen kan/mag je niet inloggen. En dan kun je dus ook geen
mail lezen.

3. Een systeembeheerder is ook maar een mens. En vergeet dus ook wel eens de
root mail te lezen.

4. Als een systeem onderuit gaat dan mis je de eventuele laatste meldingen.
Erg lastig als jij in Den Bosch zit en de doos staat in Hoogezand-
Sappermeer.

Een goed geconfigureerd mail systeem is nodig voor elke Unix bak.

--
KP

Richard Rasker
10/01/03, 13:34
Op 1/10/03, 10:20:54 AM, schreef Koos Pol=20
<koos_pol@NO.nl.JUNK.compuware.MAIL.com> over het thema Re: Vreemd=20
crontab/script-probleem:

> Jan Pieter wrote (Friday 10 January 2003 09:56):

> > Richard Rasker wrote:
> >
> >> en helemaal omdat ik verzuimd heb de root-mail te lezen, waaruit e.=
e.a.
> >> al snel duidelijk bleek
> >
> > Misschien handig om root mail te forwarden? In /etc/aliases:
> > root: user

> Het is niet alleen handig, het is zelfs gebruikelijk/standaard/verplic=
ht.
> Nou ja, vooruit het is niet verplicht. Een systeem zonder root alias i=
s=20
nog
> niet af:

[knip nuttige raadgevingen]

> Een goed geconfigureerd mail systeem is nodig voor elke Unix bak.

Mea culpa, en het is helemaal een beetje beschamend omdat ik een paar uu=
r=20
na mijn verzoek om hulp zelf de oplossing had gevonden (toen ik dus=20
opnieuw als root inlogde op de firewall-machine en de mail zag), maar er=
=20
zijn enkele verzachtende omstandigheden
- Ik heb (zoals wel blijkt) nog relatief weinig ervaring met=20
systeembeheer en scripts schrijven.
- Het gaat slechts om een klein netwerkje van mijn eigen bedrijf - een=20
eenmanszaak, dus ik ben de enige aan wie ik verantwoording af hoef te=20
leggen :-)

Ik heb de boel inmiddels aangepast; root-mail wordt nu keurig=20
doorgesluisd naar mijn normale werkaccount.


Wat betreft de vraag van Jan Pieter: ik had het script (samen met andere=
=20
relevante informatie) al in mijn eerste posting van deze thread=20
opgenomen, maar hier volgt het nog een keer, met een kleine aanpassing=20
ivm het ontdekte probleem. Een inhoudelijke opmerking: de automatische=20
expire is wat onnauwkeurig, maar dat is niet erg - het belangrijkste is =

dat hosts na enige tijd weer uit blocklist verdwijnen, zodat deze niet=20
eindeloos blijft groeien.
Let er verder even op dat regel 56 hier over twee regels is weergegeven =
-=20
even weer op =E9=E9n regel knutselen dus, anders gaat het mis.

Voor de rest is het een en al commentaar, dus de werking moet wel=20
duidelijk zijn. En natuurlijk ben ik ook een en al oor voor commentaar=20
van jullie kant - er zal vast wel het nodige aan te verbeteren zijn.
=
=20
=20
Richard Rasker




#!/bin/bash
#
# blockcheck v. 1.0
# 08-01-2003
# Auteur: R.E.Rasker - rasker@linetec.nl
# http://www.linetec.nl/
#
# Dit script kan automatisch grote vervuilers van bijvoorbeeld
# webserver-logbestanden identificeren, in een blocklist opslaan
# en via een iptables-firewall blokkeren. In de blocklist wordt
# tevens de datum opgeslagen waarop een host is toegevoegd, zodat
# deze na een bepaalde expire-tijd ook weer automatisch uit de
# blocklist verwijderd kan worden.
#
# Het firewall-script zelf moet de volgende code bevatten om de
# blocklist automatisch te verwerken; deze code moet natuurlijk
# voorafgaan aan regels die toegang verlenen:
#
# for i in `grep -v "^#" /usr/local/etc/blocklist.db | cut -d : -f 1`; d=
o
# /sbin/iptables -A INPUT -i eth0 -s $i -j block
# done
#
#
# Variabelen en vaste waarden:
# ERRMIN geeft aan hoe vaak een bepaald verdacht IP-adres minimaal
# in het error-log moet voorkomen om automatisch geblokkeerd te worden.
# EXPIRE geeft aan na hoeveel tijd een IP-adres weer toegang krijgt
# (de honderdtallen geven de maanden aan).
# ERRLOG geeft de locatie aan van het Apache error-log.
# BLOCKLIST geeft de locatie aan van de blocklist; let op dat deze
# locatie ook in het firewall-script wordt gebruikt (zie boven).
# FIREWALL geeft de locatie aan van het firewall-script.
# De variabele FIRESTART geeft aan of de firewall uiteindelijk
# opnieuw gestart moet worden.

ERRMIN=3D10
EXPIRE=3D100
ERRLOG=3D/var/log/httpd/error_log
BLOCKLIST=3D/usr/local/etc/blocklist.db
FIREWALL=3D/usr/local/bin/init_firewall
FIRESTART=3Dfalse

#
# Allereerst wordt de huidige datum bepaald in een simpel formaat:
#

DATENOW=3D`date +%y%m%d`

#
# Met de volgende opdracht wordt gezocht naar hosts die pogen requests
# uit te voeren voor Windows-systeembestanden (zoals bij Nimda) of
# buffer-overflows (zoals bij CodeRed).
# De genoemde worms zijn de grootste logvervuilers:
#

for i in `grep "winnt.*exe\|NNNNNNNNNNN" $ERRLOG | sed -e 's/^.*\[client=
=20
//g' -e 's/\].*$//g' | sort -u`; do

#
# Als een host al in de blocklist voorkomt, moet dit gesignaleerd worden=
:
#

MATCH=3Dfalse
for j in `grep -v "^#" $BLOCKLIST | cut -d : -f 1`; do
if [ $i =3D $j ]; then
MATCH=3Dtrue
fi
done

#
# Als een host niet in de blocklist voorkomt, kijk dan of deze minstens
# het opgegeven aantal keren in ERRLOG voorkomt; zo ja, voeg de host
# dan toe aan de blocklist, samen met de datum, en signaleer dat de
# firewall opnieuw gestart moet worden:
#

if [ $MATCH =3D false ]; then
if [ `grep -c $i $ERRLOG` -gt $ERRMIN ]; then
echo $i":"$DATENOW >> $BLOCKLIST
FIRESTART=3Dtrue
fi
fi
done

#
# Voor de automatische expire van hosts in de blocklist wordt alleen
# gekeken naar de datum. Zodra een expired host wordt gevonden, wordt
# dit gesignaleerd om de firewall te kunnen aanpassen. Hosts die niet
# expired zijn, komen in een tijdelijk bestand terecht, dat na de
# for-lus BLOCKLIST vervangt. Met de eerste grep-opdracht worden
# eventuele commentaarregels behouden.
#

grep "#" $BLOCKLIST > $BLOCKLIST.tmp
for HOST in `grep -v "^#" $BLOCKLIST`; do
BLOCKDATE=3D`echo $HOST | cut -d : -f 2`
if [ `expr $DATENOW - $BLOCKDATE` -gt $EXPIRE ]; then
FIRESTART=3Dtrue
else
echo $HOST >> $BLOCKLIST.tmp
fi
done
mv $BLOCKLIST.tmp $BLOCKLIST

#
# Als hosts aan BLOCKLIST zijn toegevoegd dan wel uit BLOCKLIST zijn
# verwijderd, wordt de firewall opnieuw gestart:
#

if $FIRESTART =3D true; then
$FIREWALL
fi