{"id":344,"date":"2013-07-02T17:43:35","date_gmt":"2013-07-02T15:43:35","guid":{"rendered":"https:\/\/paul-anton.vanhandel.at\/?p=344"},"modified":"2026-07-30T17:42:15","modified_gmt":"2026-07-30T15:42:15","slug":"ein-einfaches-centos-6-4-lamp-system","status":"publish","type":"post","link":"https:\/\/paul-anton.vanhandel.at\/?p=344","title":{"rendered":"ein einfaches CentOS 6.4 (6.5) LAMP-System"},"content":{"rendered":"<p><strong>Update 28. Feb 2014:<\/strong> Mittlerweile wird durch ein <em>yum update<\/em> automatisch auf CentOs 6.5 upgedated.<\/p>\n<p>Mehr als kleine Erinnerung f\u00fcr mich selbst beschreibe ich hier, wie ein einfaches, aber abgesichertes LAMP-System eingerichtet wird.<\/p>\n<p>(Wenn man statt MySQL lieber PostgreSQL installiert, dann f\u00fchrt <a title=\"CentOS 6.4 \u2013 PostgreSQL 9.2 statt MySQL \u2013 von LAMP zu LAPP\" href=\"https:\/\/paul-anton.vanhandel.at\/2013\/07\/04\/centos-6-4-postgresql-9-2-statt-mysql-von-lamp-zu-lapp\/\">dieser Weg<\/a> dorthin)<\/p>\n<p>Unser Ziel ist eine funktionierende LAMP-Umgebung, auf die dann je nach Bedarf ausgebaut werden kann.<br \/>\nAls Betriebssystem verwende ich CentOS, derzeit in der Version 6.4, und auch nur damit sind die folgenden Anweisungen getestet.<\/p>\n<p>Der Ausgangspunkt ist eine CentOS 6.4 Minimalinstallation, die man auf verschieden Weise bewerkstelligen bzw. von verschiedenen Quellen beziehen kann. Darauf gehe ich hier nicht ein und setze eine funktionierende Erstinstallation voraus. In der Folge werde ich auch nicht alle Schritte bis ins letzte Detail erkl\u00e4ren. Es gibt ausreichend Dokumentation zu allen Bereich im Internet und dieser Post soll nur eine Ged\u00e4chtnisst\u00fctze sein und kein Lehrgang. Ich kann nur empfehlen, sich \u00fcber alle Schritte &#8211; wenn nicht klar ist, warum sie gesetzt werden, oder die Implikationen, die sich daraus ergeben &#8211; zu informieren.<br \/>\nEin Linux-System sollte niemals via copy&#8217;n&#8217;paste aus einem Tutorial aufgesetzt werden. Es ist wichtig zu verstehen, warum etwas gemacht wird. Dies w\u00fcrde allerdings den Rahmen dieses Posts sprengen!<\/p>\n<p>Wir haben also ein laufendes System mit nur einem Benutzer &#8211; root. Ob der Zugriff am Server selbst oder \u00fcber ein Terminal erfolgt, ist unerheblich, Vorraussetzung ist nat\u00fcrlich, da\u00df das grundlegende Netzwerk l\u00e4uft. Es schadet sicherheitshalber aber nicht, auch Direktzugriff zu haben, wenn man insbesondere bei der Firewall etwas vergeigt. Im Grund reicht es aber, den Server remote neu starten zu k\u00f6nnen.<\/p>\n<p>Legen wir also los:<\/p>\n<p>Zuerst installieren wir uns drei Tools, die wir auf jeden Fall immer ben\u00f6tigen werden: vim (OK, vi ist an Bord und t\u00e4te es auch, aber ich bin vim gew\u00f6hnt) , wget und man. Statt vim kann es nat\u00fcrlich auch zB nano sein &#8211; irgend ein Editor halt, den ihr gew\u00f6hnt seid.<\/p>\n<pre>yum install -y vim wget man<\/pre>\n<p>Nun schalten wir SELinux aus &#8211; ein Server braucht das eher weniger:<\/p>\n<p>in <span style=\"background-color: #ffffcc;\">\/etc\/selinux\/config<\/span> setzen wir<\/p>\n<pre>SELINUX=disabled<\/pre>\n<p>Nun sollten wir rebooten (nur so wird das wirksam), zuvor nehmen wir aber noch ein paar \u00c4nderungen am Netzwerk vor.<\/p>\n<p>Als Entr\u00fcmpelungsma\u00dfnahme entfernen wir IPv6, es gibt zur Zeit keine brauchbaren Tools daf\u00fcr:<\/p>\n<p>Mit<\/p>\n<pre>ip addr<\/pre>\n<p>sehen wir erst einmal, ob IPv6 \u00fcberhaupt aktiviert ist.<\/p>\n<p><span style=\"font-family: 'courier new', courier;\"><code>1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 16436 qdisc noqueue state UNKNOWN<br \/>\nlink\/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00<br \/>\ninet 127.0.0.1\/8 scope host lo<br \/>\n<span style=\"color: red;\">inet6 ::1\/128 scope host <\/span><br \/>\nvalid_lft forever preferred_lft forever<br \/>\n2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000<br \/>\nlink\/ether c8:60:00:be:44:00 brd ff:ff:ff:ff:ff:ff<br \/>\ninet 5.9.59.15 peer 5.9.59.1\/32 brd 5.9.59.31 scope global eth0<br \/>\n<span style=\"color: red;\">inet6 fe80::ca60:ff:febe:4400\/64 scope link <\/span><br \/>\nvalid_lft forever preferred_lft forever<\/code><\/span><\/p>\n<p>Weg damit:<\/p>\n<p>Wir legen eine Datei in <span style=\"background-color: #ffffcc;\">\/etc\/modprobe.d<\/span> an und nennen sie zum Beispiel <span style=\"background-color: #ffffcc;\">disable-ipv6.conf<\/span>.<br \/>\nIn diese schreiben wir<\/p>\n<pre>install ipv6 \/bin\/true<\/pre>\n<p>in <span style=\"background-color: #ffffcc;\">\/etc\/sysconfig\/network<\/span> f\u00fcgen wir folgende Zeilen hinzu &#8211; bei der Gelegenheit sollten wir auch gleich unseren Hostnamen setzten, soferne noch n\u00f6tig. Alle andere Zeilen (DHCP etc) sollten bei der Installation schon richtig gesetzt worden sein.<\/p>\n<pre>HOSTNAME=yourhost.yourdomain.tld\r\nNETWORKING_IPV6=no\r\nIPV6INIT=no<\/pre>\n<p>Bevor wir nun einen Reboot ausf\u00fchren &#8211; SELinux ist ja noch nicht deaktiviert und die Netzwerk\u00e4nderungen wollen aktiv werden &#8211; ist dies ein guter Zeitpunkt, erst einmal ein generelles Update zu machen &#8211; je nach Quelle ist die Minimalinstallation ja nicht unbedingt ganz auf der H\u00f6he. Daher folgt nun ein<\/p>\n<pre>yum -y update<\/pre>\n<p>und nun booten wir erst einmal neu &#8211; sicherheitshalber schalten wir vorher noch die Firewall aus, um auf jeden Fall wieder remote einloggen zu k\u00f6nnen.<\/p>\n<pre>service iptables stop; reboot<\/pre>\n<p>(F\u00fcr die \u00c4nderung am Netzwerk w\u00fcrde auch ein init 3 gereicht haben, \u00fcbrigens.)<\/p>\n<p>Edit: Ich arbeite gerade an einer Centos 6.4 minimal Installation, wo die Firewall nicht aktiviert war, da hilft auch service iptables start nicht.\u00a0In diesem Fall mu\u00df man die Firewall erst generell aktivieren. Hierzu gehen wir folgenderma\u00dfen vor:<\/p>\n<p>Falls es nicht installiert installiert sein sollte:<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">yum install system-config-firewall-tui<\/pre>\n<p>Dieses Tool starten wir nun mit<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">system-config-firewall-tui<\/pre>\n<p>und erhalten eine simple GUI<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-413\" alt=\"system-config-firewall-tui\" src=\"https:\/\/paul-anton.vanhandel.at\/wp-content\/uploads\/2013\/07\/Bildschirmfoto-2013-09-17-um-17.38.15.png\" width=\"382\" height=\"223\" srcset=\"https:\/\/paul-anton.vanhandel.at\/wp-content\/uploads\/2013\/07\/Bildschirmfoto-2013-09-17-um-17.38.15-300x175.png 300w, https:\/\/paul-anton.vanhandel.at\/wp-content\/uploads\/2013\/07\/Bildschirmfoto-2013-09-17-um-17.38.15.png 382w\" sizes=\"(max-width: 382px) 100vw, 382px\" \/><\/p>\n<p>Mittels &lt;LEERTASTE&gt; aktivieren wir die Firewall, unter Anpassen k\u00f6nnen wir gleich einen Eintrag f\u00fcr SSH durchf\u00fchren lassen.<\/p>\n<p><a href=\"https:\/\/paul-anton.vanhandel.at\/wp-content\/uploads\/2013\/07\/Bildschirmfoto-2013-09-17-um-18.44.21.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-414\" alt=\"system-config-firewall-tui SSH\" src=\"https:\/\/paul-anton.vanhandel.at\/wp-content\/uploads\/2013\/07\/Bildschirmfoto-2013-09-17-um-18.44.21.png\" width=\"368\" height=\"280\" srcset=\"https:\/\/paul-anton.vanhandel.at\/wp-content\/uploads\/2013\/07\/Bildschirmfoto-2013-09-17-um-18.44.21-300x228.png 300w, https:\/\/paul-anton.vanhandel.at\/wp-content\/uploads\/2013\/07\/Bildschirmfoto-2013-09-17-um-18.44.21.png 368w\" sizes=\"(max-width: 368px) 100vw, 368px\" \/><\/a><\/p>\n<p>Schlie\u00dfen-OK-Ja und die grunds\u00e4tzliche Firewall-Aktivierung ist durchgef\u00fchrt. (Nun nicht vergessen, sicherzustellen, da\u00df der iptables Dienst vorerst deaktiviert bleibt &#8211; s.o.)<\/p>\n<p>Fahren wir mit SSH fort &#8211; dem einzigen Zugang zu unserem Server, der daher besonders sicher sein soll.<\/p>\n<p>Wir werden den Port von SSH \u00e4ndern, den Superuser ausschlie\u00dfen, eine eigene Berechtigungsgruppe anlegen und \u00fcberhaupt nur Authenitifikation \u00fcber Schl\u00fcssel zulassen.<br \/>\nDas hat eventuell den Nachteil, dass man von unterwegs, sofern man nicht ein eigenes Ger\u00e4t mit g\u00fcltigem Schl\u00fcssel hat, nicht einloggen kann. In meinem Fall ist dies aber OK und es bleibt jedem selbst \u00fcberlassen, wie dicht er seinen SSH-Zugang macht.<\/p>\n<p>Bisher hatten wir nur den Superuser root, nun legen wir einen Arbeitsuser an &#8211;<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">useradd username<\/pre>\n<p>und weisen ihm ein Passwort zu:<\/p>\n<pre>passwd username<\/pre>\n<p>Nun m\u00fcssen alle Schl\u00fcssel von den Ger\u00e4ten, mit denen eingeloggt werden soll, kopiert werden, zuvor brauchen wir aber die Struktur im Heimatverzeichnis des Benutzers:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">mkdir ~\/.ssh\r\ncd ~\r\nchmod 0700 .ssh\r\ntouch .ssh\/authorized_keys\r\nchmod 0600 .ssh\/authorized_keys<\/pre>\n<p>Nun m\u00fcssen von allen Ger\u00e4ten, von denen auf den Server eingeloggt werden soll, die \u00f6ffentlichen Schl\u00fcssel kopiert werden. Dies beschreibe ich aber hier nicht weiter.<\/p>\n<p>Nun sollte man versuchsweise &#8211; unter Beobachtung von \/var\/log\/secure &#8211; einen Login-Versuch machen und sehen, ob es funktioniert. Normalerweise sind hier keine Probleme zu erwarten.<\/p>\n<p>Nun wollen wir den Port \u00e4ndern und bestenfalls einen m\u00f6glichst hohen w\u00e4hlen &#8211; Portscanner beginnen normalerweise mit 1 bzw. mit einer Liste typischer Ports, je h\u00f6her die Nummer, desto l\u00e4nger dauert es und dem Einbrecher wird langweilig &#8211; einem Script nat\u00fcrlich nicht, aber das bricht vielleicht wegen timeout ab, wie auch immer&#8230;<\/p>\n<pre>vim \/etc\/ssh\/sshd_config<\/pre>\n<p>Finde die Zeile<\/p>\n<pre>#Port 22<\/pre>\n<p>entkommentiere sie und \u00e4ndere die Portnummer:<\/p>\n<pre>Port 12322<\/pre>\n<p>Bevor wir den SSH daemon neu starten, f\u00fchren wir weitere Ma\u00dfnahmen durch:<\/p>\n<p>Wir legen eine Gruppe &#8211; zB sshusers &#8211; an und f\u00fcgen unseren Arbeitsuser der Gruppe hinzu.<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">groupadd sshusers\r\nusermod -a  -G sshusers &lt;username&gt;<\/pre>\n<p>In <span style=\"background-color: #ffffcc;\">\/etc\/ssh\/sshd_config<\/span> \u00e4ndern wir noch folgendes (finde und entkommentiere\/ersetze oder f\u00fcge hinzu, falls nicht vorhanden)<\/p>\n<pre>PermitRootLogin no\r\nMaxAuthTries 1\r\nPubkeyAuthentication yes\r\nAuthorizedKeysFile .ssh\/authorized_keys\r\nUsePAM no\r\nPasswordAuthentication no\r\nKerberosAuthentication no\r\nGSSAPIAuthentication no\r\nAllowGroups sshusers\r\nMaxStartups 2<\/pre>\n<p>Nun entfernen wir noch die aktuellen host keys<\/p>\n<pre>rm -f \/etc\/ssh\/ssh_host*key*<\/pre>\n<p>und starten endlich den sshd (service sshd restart) neu. Sinnvollerweise lassen wir unser Terminal offen und versuchen \u00a0einen neuen Login in einem weiteren Terminal, falls es nicht funktioniert, haben wir immer noch unser altes. Es sollte aber alles funktionieren soweit. (Nicht vergessen, der Port ist ge\u00e4ndert, dies mu\u00df dem SSH client mitgeteilt werden ( -p 12322).<\/p>\n<p>Versuche auch, mit root einzuloggen, es sollte nicht funktionieren.<\/p>\n<p>Nun haben wir also einen einigerma\u00dfen sicheren SSH Zugang, aber die Firewall l\u00e4uft noch nicht. Bei einer normalen Installation von CentOS 6.4 minimal sollte eine Zeile f\u00fcr SSH angelegt worden sein. Wir \u00f6ffnen<\/p>\n<pre>\/etc\/sysconfig\/iptables<\/pre>\n<p>und \u00e4ndern die Portnummer.<\/p>\n<p>Simpel sieht die Zeile so aus:<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">-A INPUT -m state --state NEW -m tcp -p tcp --dport 12322 -j ACCEPT<\/pre>\n<p>Nun starten wir die Firewall und wenn wir Gl\u00fcck haben, sollten wir immer noch auf der Konsole arbeiten k\u00f6nnen. Nunja, mit Gl\u00fcck hat es weniger zu tun, aber die F\u00e4lle, wo man sich durch eine Fehlkonfiguration der FW aus einem System gesperrt hat, sind Legion. Bei einem lokalen Rechner ist das nicht weiter tragisch, problematischer wird es bei einem Server, wo man nicht lokal einloggen kann. Zumindest die M\u00f6glichkeit, den Server aus der Ferne zu Resetten sollte aber gegeben sein, und hier w\u00fcrde sich empfehlen, \u00c4nderungen an der FW nicht in <span style=\"background-color: #ffffcc;\">\/etc\/sysconfig\/iptables<\/span> zu machen, sondern von der Kommandozeile aus. Wenn dann was schiefgeht, kann man immer noch rebooten und hat die FW im alten Zustand, soferne man nicht mittels <span style=\"background-color: #ffffcc;\">service iptables save<\/span> die \u00c4nderungen gespeichert hat. Hierzu werde ich vielleicht sp\u00e4ter einmal einen eigenen Post schreiben.<\/p>\n<p>Nun ist also SSH relativ dicht und die FW werkelt auch, kommen wir nun zu einem gerne \u00fcbersehenen, aber f\u00fcr alle m\u00f6glichen Dinge &#8211; wie zum Beispiel Logdaten &#8211; nicht ganz unwichtigem Punkt.<\/p>\n<p>Die Serverzeit:<\/p>\n<p>Wir installieren den ntp daemon &#8211; einfach mit<\/p>\n<pre>yum -y install ntp<\/pre>\n<p>und schalten ihn ein<\/p>\n<pre>chkconfig ntpd on<\/pre>\n<p>Nun synchronisieren wir die Zeit mittels<\/p>\n<pre>ntpdate pool.ntp.org<\/pre>\n<p>oder, wenn ihr einen anderen Zeitserver verwenden wollt, nehmt den.<br \/>\nNun noch den daemon starten und nie mehr zu sp\u00e4t kommen \ud83d\ude42<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\"> service ntpd start<\/pre>\n<p>Nunmehr ist es Zeit, sich ein wenig dem AMP zu widmen. Es ist vorerst nicht unbedingt n\u00f6tig, aber f\u00fcr einen weiteren Ausbau meist unerl\u00e4\u00dflich, einige zus\u00e4tzliche Repositories anzuzapfen, daher werden wir dies zu allererst erledigen.<\/p>\n<p>Ich verwende gerne epel und rpmforge, obwohl es da manchmal zu Konflikten kommen kann (die aber in den Repo-Settings behandelt werden k\u00f6nnen), daher werden diese nun eingerichtet. Die Links und Versionen sind mit Zeitpunkt der Ver\u00f6ffentlichung dieses Posts g\u00fcltig, das kann sich nat\u00fcrlich mittlerweile ge\u00e4ndert haben&#8230;<\/p>\n<pre>wget http:\/\/pkgs.repoforge.org\/rpmforge-release\/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm\r\nrpm -ivh rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm<\/pre>\n<pre>rpm --import https:\/\/fedoraproject.org\/static\/0608B895.txt\r\nwget http:\/\/dl.fedoraproject.org\/pub\/epel\/6\/x86_64\/epel-release-6-8.noarch.rpm\r\nrpm -ivh epel-release-6-8.noarch.rpm<\/pre>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">wget http:\/\/rpms.famillecollet.com\/enterprise\/remi-release-6.rpm\r\nrpm -Uvh remi-release-6.rpm<\/pre>\n<p>Das Remi Repo mu\u00df noch in <span style=\"background-color: #ffffcc;\">\/etc\/yum.repos.d\/remi.repo<\/span> &#8216;enabled=1&#8217; werden.<\/p>\n<p>Ich gebe Epel den Vorzug vor CentOS base, am einfachsten geht das mit Priorit\u00e4ten:<\/p>\n<pre>yum install yum-priorities<\/pre>\n<p>Wir editieren\u00a0<span style=\"background-color: #ffffcc;\">\/etc\/yum.repos.d\/epel.repo<\/span>\u00a0und f\u00fcgen eine Zeile<\/p>\n<pre>priority=10<\/pre>\n<p>der <div class=\"fusion-fullwidth fullwidth-box fusion-builder-row-1 fusion-flex-container hundred-percent-fullwidth non-hundred-percent-height-scrolling\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-overflow:visible;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap\" style=\"width:calc( 100% + 0px ) !important;max-width:calc( 100% + 0px ) !important;margin-left: calc(-0px \/ 2 );margin-right: calc(-0px \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-0 fusion_builder_column_1_1 1_1 fusion-flex-column fusion-flex-align-self-flex-start fusion-column-no-min-height\" style=\"--awb-bg-size:cover;--awb-width-large:100%;--awb-margin-top-large:0px;--awb-spacing-right-large:0px;--awb-margin-bottom-large:0px;--awb-spacing-left-large:0px;--awb-width-medium:100%;--awb-spacing-right-medium:0px;--awb-spacing-left-medium:0px;--awb-width-small:100%;--awb-spacing-right-small:0px;--awb-spacing-left-small:0px;\"><div class=\"fusion-column-wrapper fusion-flex-justify-content-flex-start fusion-content-layout-column\">[epel] Sektion hinzu.<\/p>\n<p>Nun machen wir noch einmal ein<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">yum update<\/pre>\n<p>es sollte sich dabei nicht viel tun allerdings,<\/p>\n<p>Nunmehr installieren wir die Developer Tools. Manche werden meinen, das w\u00fcrde doch ein gewisses Sicherheitsrisiko bergen, aber erstens geht es ohne schwer und zweitens, wenn einer Zugang zu unserem Server erlangen w\u00fcrde, k\u00f6nnte er das auch selbst tun, daher&#8230;<\/p>\n<pre>yum groupinstall &#039;Development Tools&#039;<\/pre>\n<p>&nbsp;<\/p>\n<p>Nun endlich installieren wir unseren AMP:<\/p>\n<pre>yum install httpd mod_ssl mysql-server php php-mysql<\/pre>\n<p>Wie ihr bemerkt, habe ich hier nur einen PHP Minimalstack installiert. Alle weiteren Module werden dann je nach Bedarf hinzugef\u00fcgt. So h\u00e4lt man die Sache schlank.<\/p>\n<p>Wir schalten Apache und MySQL ein<\/p>\n<pre>chkconfig httpd on\r\nchkconfig mysqld on<\/pre>\n<p>Bevor wir Apache starten, sollten wir in<span style=\"background-color: #ffffcc;\">\u00a0\/etc\/httpd\/conf\/httpd.conf\u00a0<\/span>den <span style=\"background-color: #ffffcc;\">ServerName<\/span> an unseren Hostname anpassen und eine g\u00fcltige ServerAdmin Emailadresse eingeben &#8211; alle weiteren Einstellungen h\u00e4ngen von Einsatzzweck des Servers ab.<\/p>\n<p>Nun starten wir den Indianer und sehen uns mal im Browser an, ob er richtig ums Lagerfeuer tanzt. Und, nanu, es funktioniert nicht &#8211; kann auch nicht, weil unsere Firewall es verhindert. Wir m\u00fcssen sie also f\u00fcr die Ports 80 und 443 \u00f6ffnen.<\/p>\n<p>Wie wir besprochen haben, f\u00fchren wir die \u00c4nderung erst einmal auf der Konsole aus, damit wir nichts permanent kaputt machen.<br \/>\nVorher sehen wir uns aber erst einmal die aktuellen Einstellungen an.<\/p>\n<pre>iptables -L --line-numbers -n -v<\/pre>\n<p>Wir sollten etwa so etwas bekommen<\/p>\n<pre class=\"brush: bash; gutter: false\">Chain INPUT (policy ACCEPT 0 packets, 0 bytes)\r\nnum   pkts bytes target     prot opt in     out     source               destination         \r\n1     6143 8434K ACCEPT     all  --  *      *       0.0.0.0\/0            0.0.0.0\/0           state RELATED,ESTABLISHED \r\n2        0     0 ACCEPT     icmp --  *      *       0.0.0.0\/0            0.0.0.0\/0           \r\n3        0     0 ACCEPT     all  --  lo     *       0.0.0.0\/0            0.0.0.0\/0           \r\n4        1    64 ACCEPT     tcp  --  *      *       0.0.0.0\/0            0.0.0.0\/0           state NEW tcp dpt:12322 \r\n5     1635  211K REJECT     all  --  *      *       0.0.0.0\/0            0.0.0.0\/0           reject-with icmp-host-prohibited<\/pre>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)\r\nnum   pkts bytes target     prot opt in     out     source               destination         \r\n1        0     0 REJECT     all  --  *      *       0.0.0.0\/0            0.0.0.0\/0           reject-with icmp-host-prohibited<\/pre>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">Chain OUTPUT (policy ACCEPT 4561 packets, 324K bytes)\r\nnum   pkts bytes target     prot opt in     out     source               destination<\/pre>\n<p>Da sind also drei Ketten (Chains), INPUT, FORWARD und OUTPUT. Zu iptables k\u00f6nnte manwiederum Romane schreiben, hier nur ein paar Infos und Google ist Euer Freund (Yahoo &amp; Co nat\u00fcrlich auch).<\/p>\n<p>Wichtig zu wissen ist, da\u00df dies eine sehr einfache Firewall-Konfiguration ist (und jede Menge Leute daran herummeckern w\u00fcrden, denke ich mal). Sie funktioniert aber einwandfrei und mehr braucht es vorerst nicht.<\/p>\n<p>In der INPUT Kette sehen wir, \u00fcbersetzt, folgendes:<\/p>\n<p>1: alle Verbindungen von allen Quellen zu allen Destinationen durch alle Protokolle &#8211; also ALLE, die bestehen (ESTABLISHED), oder &#8216;mit einer anderen Verbindung in Beziehung (RELATED) stehen&#8217; &#8211; das kommt zB bei FTP vor und ich will hier nicht n\u00e4her darauf eingehen, sind zugelassen.<\/p>\n<p>2: alle ICMP Requests werden bedient &#8211; einfachstes Beispiel, es wird auf einem remote Ping geantwortet. Es gibt eigentlich keinen Grund, so etwas nicht zuzulassen, aber man kann im Rahmen der Diskussion, wie man seinen Server am besten &#8216;unsichtbar&#8217; macht, wohl dar\u00fcber diskutieren. Ich bin kein Freund von DROP, aber dazu sp\u00e4ter.<\/p>\n<p>3: alle internen Verbindungen sind erlaubt &#8211; Wenn die daemons sich \u00fcber lo unterhalten wollen, dann sollen sie doch&#8230;<\/p>\n<p>4: Das ist die Regel, durch die wir mit dem SSH-Client von der Ferne eine neue Verbindung aufmachen d\u00fcrfen. Man k\u00f6nnte hier noch eine oder mehrere fixe IPs eintragen, von denen man einloggen darf, bei mir ist das unpraktisch, daher lasse ich es.<\/p>\n<p>5: Alles andere wird abgelehnt. Punkt<\/p>\n<p>Die FORWARD Kette l\u00e4\u00dft ganz einfach nichts durch, wo wir weder Ursprung noch Ziel sind &#8211; wir sind kein Relay von irgendwas, also kein Durchhaus, wo jeder nach belieben durchlatschen darf. Immer erinnert, da\u00df dies ein LAMP-Server sein will und nichts anderes. Man k\u00f6nnte in der Policy auch DROP verwenden und w\u00fcrde sich die Regel sparen, aber ich finde, lieber aktiv verweigern als still unter den Tisch kehren.<\/p>\n<p>OUTPUT hat gar keine Regeln, wir lassen alles raus &#8211; (policy ACCEPT) hat das zu verantworten.<\/p>\n<p>Nun ist es aber an der Zeit, unserem Indianer das Tipi aufzusperren.<br \/>\nWir wollen das nun einmal nicht in der Konfigurationsdatei bearbeiten, sondern erst einmal von der Konsole die Regeln hinzuf\u00fcgen:<\/p>\n<pre>iptables -I INPUT 4 -m state --state NEW -p tcp --dport 80 -j ACCEPT\r\niptables -I INPUT 4 -m state --state NEW -p tcp --dport 443 -j ACCEPT<\/pre>\n<p>Die Regeln in den einzelnen Chains werden hintereinander abgearbeitet, bis eine zutrifft. Diese wird dann ausgef\u00fchrt und Schlu\u00df. Daher ist es auch wichtig, hier keine Regel einfach anzuf\u00fcgen, sondern wir schieben sie hinein, zumindest vor die Regel, die in unserer INPUT chain alles verwirft. Sonst kommen diese neuen Regeln n\u00e4mlich nie zum Zuge und das Kriegsbeil wird ausgegraben.<\/p>\n<p>Im Browser sollte nun die freundliche Apache 2 Test Page zu sehen sein, sowohl unter http:\/\/ als auch unter https:\/\/. Ein tempor\u00e4res Server Zertifikat wurde bei der Installation freundlicherweise gleich mitgeliefert.<\/p>\n<p>\u00dcbrigens: HTTP ist ein zustandsloses Protokoll, daher macht es keinen Sinn, die FW-Regeln f\u00fcr bereits etablierte (ESTABLISHED) Verbindungen einzurichten.<\/p>\n<p>Wenn nun alles funktioniert, speichern wir die hinzugef\u00fcgten Firewall-Regeln ab, die sind sonst n\u00e4mlich nach dem n\u00e4chsten Start wieder verschwunden.<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">service iptables save<\/pre>\n<p>Im Wesentlichen war&#8217;s das, was uns vielleicht noch fehlt, ist ein wenig logging. Wir wollen ja schlie\u00dflich wissen, was unsere Fierewall so macht. Wir legen eine neue Chain LOGGING an und verschieben den INPUT REJECT (den von FORWARD gleich mit) nach LOGGING.<br \/>\nNun allerdings ohne weiteren Kommentar ist hier die nach dieser Aktion g\u00fcltige Konfigurationsdatei:<\/p>\n<pre class=\"brush: bash; gutter: false\">*filter\r\n:INPUT ACCEPT [0:0]\r\n:FORWARD ACCEPT [0:0]\r\n:OUTPUT ACCEPT [133:26943]\r\n:LOGGING - [0:0]\r\n-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT \r\n-A INPUT -p icmp -j ACCEPT \r\n-A INPUT -i lo -j ACCEPT \r\n-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT \r\n-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT \r\n-A INPUT -p tcp -m state --state NEW -m tcp --dport 12322 -j ACCEPT \r\n-A INPUT -j LOGGING \r\n-A FORWARD -j LOGGING \r\n-A LOGGING -m limit --limit 2\/min -j LOG --log-prefix &quot;IPTables-Dropped: &quot; \r\n-A LOGGING -j REJECT --reject-with icmp-host-prohibited \r\nCOMMIT<\/pre>\n<p>Was hier passiert ist, da\u00df einfach die letzte Zeile der INPUT-Chain, sowie die FORWARD-Chain, die ja beide den Zugriff blocken sollen, zuerst zur LOGGING-Chain weitergereicht werden. Die LOGGING-Chain schreibt alles, was sie dargereicht bekommt, ins Protokoll und weist dann die Anfrage zur\u00fcck. Anfragen, die vorher von einer der anderen INPUT-Regeln mit wohlwollen durchgelassen wurden, kommen hier nat\u00fcrlich nicht an und damit auch nicht ins Log.<\/p>\n<p>Wird jetzt die Firewall gestartet, loggt sie nach <span style=\"background-color: #ffffcc;\">\/var\/log\/messages<\/span> &#8211; das wollen wir noch \u00e4ndern!<\/p>\n<pre>vim \/etc\/rsyslog.d\/iptables.conf<\/pre>\n<p>Dort kommt folgende Zeile hinein:<\/p>\n<pre>:msg, contains, &quot;IPTables-Dropped: &quot; -\/var\/log\/iptables.log<\/pre>\n<p>und den Logger mit<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\"> service rsyslog restart<\/pre>\n<p>neu starten. Klar, was passiert, oder?<\/p>\n<p>Ein Log-File will sich drehen, wir brauchen Rotation. Die sollten wir f\u00fcr jedes neue Logfile immer einrichten, damit nicht irgendwann einmal (in 10 Tagen\/Monaten\/Jahren oder so) pl\u00f6tzlich kein Platz mehr auf der Platte ist, oder die Datei korrupt oder sonstwas passiert.<\/p>\n<p>Eine neue Konfigurationsdatei f\u00fcr logrotate mu\u00df also her:<\/p>\n<pre>vim \/etc\/logrotate.d\/iptables<\/pre>\n<p>da hinein kommt<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">\/var\/log\/iptables.log {\r\n    missingok\r\n    notifempty\r\n    rotate 4\r\n    weekly\r\n    size 30k\r\n    nocompress\r\n    create 0600 root root\r\n}<\/pre>\n<p>Man lese man, wenn man mehr dar\u00fcber wissen m\u00f6chte \ud83d\ude09<\/p>\n<p>Ein weiteres nettes Tool zur Absicherung des Servers ist <a title=\"fail2ban\" href=\"http:\/\/www.fail2ban.org\">fail2ban<\/a>.<\/p>\n<p>fail2ban &#8211; um es kurz zu machen &#8211; blockiert IP-Adressen, von denen zu oft in zu kurzer Zeit versucht wird, sich erfolglos zB via SSH einzuloggen. Dies kann passieren, wenn man sein Passwort vergessen hat (schlecht), \u00fcberhaupt erst das Einloggen mittels Passwort statt Keys erlaubt (noch schlechter) oder ein \u00fcbelwollender Mensch versucht, Kontrolle \u00fcber unseren Server zu bekommen (weniger schlecht, weil wir erwischen ihn mit fail2ban).<\/p>\n<p>Die Installation ist denkbar einfach. Da wir schon das Epel Repo eingerichtet haben, machen wir das mit yum:<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">yum install fail2ban<\/pre>\n<p>Zwischendurch mal ganz allgemein zu yum: Mit der Option -y kann man \u00fcbrigens eine Installation ohne weitere Zwischenabfragen durchf\u00fchren, auch wenn bei der Installation erst noch andere Pakete installiert werden m\u00fcssen, von denen das eigentliche Paket abh\u00e4ngt. Ich verwende es nur in den wenigsten F\u00e4llen, weil ich mir doch lieber gerne erst ansehe, was denn da auf die Platte kommen soll.<\/p>\n<p>Zur\u00fcck zu fail2ban. Nach der Installation ist ein wenig Konfiguration angesagt. Die Konfigurationsdateien befinden sich unter <span style=\"background-color: #ffffcc;\">\/etc\/fail2ban\/<\/span><\/p>\n<p>Der daemon selbst wird in der Datei <span style=\"background-color: #ffffcc;\">fail2ban.conf<\/span> konfiguriert. Hier gibt es nicht allzuviel zu tun, im Grunde braucht man es gar nicht angreifen. Was ich vorzugsweise \u00e4ndere ist der Ort f\u00fcr die logs. Standardm\u00e4\u00dfig (Version 0.8.10) ist das der SYSLOG, ich hab lieber ein eigenes Logfile, daher \u00e4ndere ich das <span style=\"background-color: #ffffcc;\">logtarget<\/span>.<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">logtarget = \/var\/log\/fail2ban.log<\/pre>\n<p>Wo ein Log da Rotation, wir erinnern uns.<\/p>\n<p>Nun zur Konfiguration der Regeln, nach denen fail2ban seine Mauern aufzieht.<br \/>\nDiese findet man unter \/etc\/fail2ban\/jail.conf<\/p>\n<p>Die einzelnen Eintr\u00e4ge sind ziemlich selbsterkl\u00e4rend, wichtig ist der Teil [ssh-iptables], der normalerweise in der Konfigurationsdatei schon enthalten ist.<\/p>\n<p>Hier ein Beispiel:<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">[ssh-iptables]\r\n\r\nenabled  = true\r\nfilter   = sshd\r\naction   = iptables[name=SSH, port=12322, protocol=tcp]\r\n           sendmail-whois[name=SSH, dest=root, sender=fail2ban@your.server.com]\r\nlogpath  = \/var\/log\/secure\r\nmaxretry = 5<\/pre>\n<p>Wichtig ist, die zuvor ge\u00e4nderte Portnummer von ssh &#8211; in unserem Beispiel 12322 &#8211; zu verwenden. Die Email-Adresse, die als Absender f\u00fcr Meldungen verwendet wird, kann man auch noch \u00e4ndern.<\/p>\n<p>Dabei wollen wir es belassen, nat\u00fcrlich kann fail2ban viel mehr, aber f\u00fcrs Erste reicht uns das, die Hauptarbeit mu\u00df ohnehin die Firewall erledigen.<\/p>\n<p>Nun stellen wir sicher, da\u00df fail2ban auch immer brav startet<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">chkconfig fail2ban on<\/pre>\n<p>und starten den daemon auch gleich.<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\">service fail2ban start<\/pre>\n<p>Und was, wenn man sich mal selbst mit fail2ban ausgesperrt hat. <a title=\"fail2ban manueller \u2018Notfall\u2019-unban\" href=\"https:\/\/paul-anton.vanhandel.at\/2013\/02\/12\/fail2ban-manueller-notfall-unban\/\">Hier ist die L\u00f6sung<\/a>.<\/p>\n<p>In der jail.conf gibt es, falls das jemandem aufgefallen ist, einen Eintrag dest=root. Das bedeutet nichts anderes, als das fail2ban seine Fehlermeldungen an den lokalen Benutzer root schickt. Nicht nur dieser Dienst macht das, auch andere verwenden lokale Adressen.<\/p>\n<p>Da wir nicht jedesmal umst\u00e4ndlich in den lokalen Postf\u00e4chern nachsehen wollen, hier kurz ein Ausflug zu Aliases, dem lokalen Adressbuch. Es befindet sich in <span style=\"background-color: #ffffcc;\">\/etc\/aliases<\/span>. Sieht man sich diese Datei an, stellt man schnell fest, das fast alles auf root umgeleitet wird. Nun wollen wir root selbst auf eine echte Email-Adresse, die wir auch bequem in unserem Desktop-Client lesen k\u00f6nnen, umleiten. Hierzu f\u00fcgen wir einfach ganz unten eine Zeile ein, die auf diese Adresse deutet.<\/p>\n<pre class=\"brush: bash; gutter: false; first-line: 1\"># Person who should get root&#039;s mail\r\nroot:           webmaster@deinedomain.eu<\/pre>\n<p>Abspeichern und fertig.<\/p>\n<p>Jetzt sollten wir einmal ein paar PHP Einstellungen vornehmen, die einfach sein sollen.<\/p>\n<p>Die php.ini befindet sich in <span style=\"background-color: #ffffcc;\">\/etc\/php.ini<\/span> und wir \u00e4ndern hier<\/p>\n<pre>date.timezone = Europe\/Vienna (oder was immer euch am n\u00e4chsten kommt)\r\nlog_errors = On\r\nerror_log = \/tmp\/php_errors.log (oder anderswo - wenn anderswo: Es mu\u00df f\u00fcr Apache schreibbar sein)\r\ndisplay_startup_errors = On (oder auch nicht, je nach dem...)\r\nerror_reporting = (was immer ihr f\u00fcr n\u00f6tig haltet, aber verwendet es)<\/pre>\n<p>Apache neu starten!<\/p>\n<p>Schlie\u00dflich machen wir mysql noch ein wenig sicherer, mit den Einstellungen werden wir uns ansonsten hier nicht weiter besch\u00e4ftigen, dar\u00fcber kann man weitere 100 Seiten schreiben.<\/p>\n<p>Erstmal mysql starten, wenn noch nicht geschehen:<\/p>\n<pre>service mysqld start<\/pre>\n<p>und nun einfach<\/p>\n<pre>\/usr\/bin\/mysql_secure_installation<\/pre>\n<p>laufen lassen, f\u00fcr root ein sch\u00f6nes Passwort ausdenken und sonst brav immer Yes sagen.<\/p>\n<p>Wenn auf mysql auch entfernt zugegriffen werden soll, mu\u00df in der Fierwall eine entsprechende Regel eingef\u00fcgt werden.<\/p>\n<p>Damit haben wir in aller K\u00fcrze ein grundlegendes LAMP-System eingerichtet, welches nun je nach Einsatzzweck ausgebaut werden kann.<\/p>\n<p>Noch einmal ein Appell am Schluss: Macht niemals einfach copy&#8217;n&#8217;paste, denkt \u00fcber das, was ihr macht, nach, lest in den man pages oder im Internet, damit ihr auch versteht, was ihr da tut. Dann ist das alles keine Hexerei und macht sogar Spa\u00df.<\/p>\n<p>Danke f\u00fcrs Lesen und ich freue mich immer auf Kommentare!<\/div><\/div><\/div><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update 28. Feb 2014: Mittlerweile wird durch ein yum update automatisch auf CentOs 6.5 upgedated. Mehr als kleine Erinnerung f\u00fcr mich selbst beschreibe ich hier, wie ein einfaches, aber abgesichertes LAMP-System eingerichtet wird. (Wenn man statt MySQL lieber PostgreSQL installiert, dann f\u00fchrt dieser Weg dorthin) Unser Ziel ist eine funktionierende LAMP-Umgebung, auf die dann je <a href=\"https:\/\/paul-anton.vanhandel.at\/?p=344\"> [&#8230;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[40,1,15,48,11,47],"tags":[63,58,62,50,51,67,49,64,61,65,66],"class_list":["post-344","post","type-post","status-publish","format-standard","hentry","category-40","category-allgemein","category-lamp","category-linux","category-php","category-sicherheit","tag-apache","tag-centos-6-4","tag-einsteiger","tag-fail2ban","tag-iptables","tag-lamp","tag-linux-2","tag-mysql","tag-php","tag-webserver","tag-webserver-einrichten"],"_links":{"self":[{"href":"https:\/\/paul-anton.vanhandel.at\/index.php?rest_route=\/wp\/v2\/posts\/344","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/paul-anton.vanhandel.at\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/paul-anton.vanhandel.at\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/paul-anton.vanhandel.at\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/paul-anton.vanhandel.at\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=344"}],"version-history":[{"count":1,"href":"https:\/\/paul-anton.vanhandel.at\/index.php?rest_route=\/wp\/v2\/posts\/344\/revisions"}],"predecessor-version":[{"id":883,"href":"https:\/\/paul-anton.vanhandel.at\/index.php?rest_route=\/wp\/v2\/posts\/344\/revisions\/883"}],"wp:attachment":[{"href":"https:\/\/paul-anton.vanhandel.at\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=344"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/paul-anton.vanhandel.at\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=344"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/paul-anton.vanhandel.at\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=344"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}