Palvelinten hallinta - Harjoitus 2 ============== *Disclaimer:* -------------- Tämä harjoitus on tehty osana Haaga-Helian Tietojenkäsittelyn koulutusohjelman kurssia [Palvelinten hallinta (ICT4TN022, kevät 2018)](http://www.haaga-helia.fi/fi/opinto-opas/opintojaksokuvaukset/ICT4TN022). Kurssin pitäjänä toimii [Tero Karvinen](http://terokarvinen.com/), joka on määritellyt tämän harjoituksen tehtävänkuvaukset. Tehtävien vastaukset ovat Pekka Heleniuksen (allekirjoittanut) tuottamia. b) Laita käyttäjien kotisivut toimimaan Apachella - Salt -------------- **Vastaus:** Olemme tässä vaiheessa luoneet perusedellytykset Masterille ja Minione(ille). Ks. [harjoitus 1](https://github.com/Fincer-altego/central-management-of-multiple-servers/blob/master/h1.md) Luodaan Master-koneen kansioon _/srv/salt_ state-tiedosto *0_create_indexhtml.sls* komennolla *sudo nano /srv/salt/0_create_indexhtml.sls* ja täydennetään se sisällöllä: ``` # This is a Salt script for installing Apache HTTP daemon with # default userdir configuration to minion computers # Author: Pekka Helenius (~Fincer), 2018 ######################################### # Install Apache HTTP daemon to minions install_httpd_daemon: pkg.installed: - pkgs: - apache2 ######################################### # Enable Apache userdir module httpd_userdir: cmd.run: - name: /usr/sbin/a2enmod userdir - require: - pkg: install_httpd_daemon ######################################### # Replace default index.html content httpd_foo-index: cmd.run: - name: /bin/echo "foo" > /var/www/html/index.html - require: - cmd: httpd_userdir - pkg: install_httpd_daemon ######################################### # Execute public_html script execute_public_html: cmd.script: - name: salt://0_create_indexhtml.sh - runas: root ######################################### # Restart Apache HTTP daemon httpd_service_restart_userdir: service.running: - name: apache2.service - watch: - cmd: httpd_userdir ``` Tiedoston oikeudet tulisi olla: u=rw, g=r, o=r (0644) Harjoituksessa käytetään Debian-pohjaisia Xubuntu-käyttöjärjestelmiä (18.04 LTS). Varmistetaan, että "orja" -alkuisiin orjakoneisiin (minions) saadaan yhteys suorittamalla master-koneella esim. komento: ``` [09/04/2018 22:01:26 - fincer: ~ ]$ sudo salt 'orja*' grains.item osrelease orjakone: ---------- osrelease: 18.04 ``` Luodaan master-koneelle seuraava shell-skripti */srv/salt/0_create_indexhtml.sh*, joka tuottaa kaikille orjakoneen käyttäjille kansion *public_html* testisivuineen: ``` #!/bin/sh # Find home folders of system users (who are using bash as their default shell) for userhome in $(grep -E "\/bin\/bash" /etc/passwd | grep -v root | awk -F ':' '{print $(NF - 1)}'); do # Create public_html for found user if [ ! -d "${userhome}"/public_html ]; then mkdir -p "${userhome}"/public_html # Promote this user to be the owner of the created directory chown $(stat --format "%u:%g" ${userhome}) "${userhome}"/public_html # Touch default index file for testing purposes echo "This is my test site. I am user $(stat --format \"%U\" ${userhome}). Happy coding!" > "${userhome}"/public_html/index.html fi done ``` Suoritetaan tehtävänannossa edellytetty Apache HTTP-daemonin asennus minion-koneille: ``` sudo salt 'orja*' state.apply 0_create_indexhtml ``` Esimerkki-output (masterilla): ``` [09/04/2018 21:45:41 - fincer: salt ]$ sudo salt 'orja*' state.apply 0_create_indexhtml orjakone: ---------- ID: install_httpd_daemon Function: pkg.installed Result: True Comment: All specified packages are already installed Started: 03:06:06.583325 Duration: 377.198 ms Changes: ---------- ID: httpd_userdir Function: cmd.run Name: /usr/sbin/a2enmod userdir Result: True Comment: Command "/usr/sbin/a2enmod userdir" run Started: 03:06:06.962361 Duration: 19.784 ms Changes: ---------- pid: 20406 retcode: 0 stderr: stdout: Module userdir already enabled ---------- ID: httpd_foo-index Function: cmd.run Name: /bin/echo "foo" > /var/www/html/index.html Result: True Comment: Command "/bin/echo "foo" > /var/www/html/index.html" run Started: 03:06:06.982499 Duration: 3.978 ms Changes: ---------- pid: 20411 retcode: 0 stderr: stdout: ---------- ID: execute_public_html Function: cmd.script Name: salt://0_create_indexhtml.sh Result: True Comment: Command 'salt://0_create_indexhtml.sh' run Started: 03:06:06.986594 Duration: 415.176 ms Changes: ---------- pid: 20432 retcode: 0 stderr: stdout: ---------- ID: httpd_service_restart_userdir Function: service.running Name: apache2.service Result: True Comment: Service restarted Started: 03:06:07.435663 Duration: 124.998 ms Changes: ---------- apache2.service: True Summary for orjakone ------------ Succeeded: 5 (changed=4) Failed: 0 ------------ Total states run: 5 Total run time: 941.134 ms ``` Minion-koneelta voimme tarkastaa, onko kansio *public_html* ja tiedosto *index.html* luotu (esim. orjakone:en käyttäjälle fincer): ``` [09/04/2018 21:46:59 - fincer: salt ]$ sudo salt 'orjakone' cmd.run 'cat /home/fincer/public_html/index.html' orjakone: This is my test site. I am user "fincer". Happy coding! ``` c) Laita PHP toimimaan käyttäjien kotisivuilla - Salt (Huomaa, että PHP toimii oletuksena kaikkialla muualla kuin käyttäjien public_html-kotisivuilla.) -------------- **Vastaus:** Tehtävässä pitää orjakoneilta (minions) kytkeä PHP päälle userdir-moduulin kanssa editoimalla konfiguraatiotiedostoa /etc/apache2/mods-available/php*.conf (missä * on php-versio). Tämä vaihe voidaan tehdä kahdella tavalla: - 1) Luodaan master-koneelle uusi konfiguraatiotiedosto (php*.conf) samalla sisällöllä, mutta kommentoidaan userdir-moduulin edellyttämät rivit tiedostosta (tiedostossa on selkeät ohjeet tähän) - 2) Luodaan skripti, jonka tehtävänä on lisätä kommenttimerkit orjakoneiden php*.conf -tiedoston relevanttiin osioon Molemmat vaihtoehdot määritetään suoritettavaksi master:lla Saltin state-tiedostossa. Toteutetaan vaihtoehto 2. Luodaan master-koneella shell-skripti */srv/salt/1_enable_php-for-userdir.sh* sisällöllä: ``` #!/bin/sh # Enable PHP for userdir module in Apache # Author: Pekka Helenius, 2018 PHP_CONF_FILE="$(ls /etc/apache2/mods-available/php*.conf)" IFS=" " for line in $(cat "${PHP_CONF_FILE}" | sed -n '/\/,/\<\/IfModule>/p;/\<\/IfModule>/q'); do sed_line=$(echo "${line}" | sed 's!\*!\\*!g;') sed -ir "s!${sed_line}!#${sed_line}!" "${PHP_CONF_FILE}" done unset IFS ``` Luodaan master-koneella toinenkin shell-skripti */srv/salt/1_create_indexphp.sh* seuraavalla sisällöllä: ``` #!/bin/sh # Find home folders of system users (who are using bash as their default shell) for userhome in $(grep -E "\/bin\/bash" /etc/passwd | grep -v root | awk -F ':' '{print $(NF - 1)}'); do # Create public_html for found user if [ ! -d "${userhome}"/public_html ]; then mkdir -p "${userhome}"/public_html # Promote this user to be the owner of the created directory chown $(stat --format "%u:%g" ${userhome}) "${userhome}"/public_html # Rename existing index.html if exists if [ -f "${userhome}"/public_html/index.html ]; then mv "${userhome}"/public_html/index.html "${userhome}"/public_html/index.html.old fi # Touch default index PHP file for testing purposes echo "" > "${userhome}"/public_html/index.php fi done ``` Luodaan master-koneelle state-määritystiedosto */srv/salt/1_create_indexphp.sls* sisällöllä: ``` # Author: Pekka Helenius (~Fincer), 2018 ######################################### # Variables # PHP module for Apache in Debian {% set ENABLE_PHP_MODULE = "/usr/sbin/a2enmod $(a2query -m | awk '{print $1}' | grep php)" %} {% set USERDIR_ENABLE_STATUS = "a2query -m | grep userdir | grep 'enabled by' &>/dev/null || /usr/sbin/a2enmod userdir" %} ######################################### # Install PHP addons for Apache HTTP daemon (with dependencies) install_httpd_php: pkg.installed: - pkgs: - apache2 - libapache2-mod-php ######################################### # Find if userdir module is enabled check_userdir_status: cmd.run: - name: {{ USERDIR_ENABLE_STATUS }} - require: - pkg: install_httpd_php ######################################### # Enable PHP for users execute_userdir_php_script: cmd.script: - name: salt://apache/1_enable_php-for-userdir.sh - runas: root - require: - cmd: check_userdir_status add_indexphp_files: cmd.script: - name: salt://apache/1_create_indexphp.sh - runas: root - require: - cmd: execute_userdir_php_script ######################################### # Enable PHP module (should be done already, though) enable_httpd_php: cmd.run: - name: {{ ENABLE_PHP_MODULE }} ######################################### # Restart Apache HTTP daemon httpd_service_restart_php: service.running: - name: apache2.service - watch: - cmd: check_userdir_status - cmd: execute_userdir_php_script ``` Esimerkki-output master-koneella: ``` [09/04/2018 23:13:27 - fincer: ~ ]$ sudo salt 'orjakone' state.apply 1_create_indexphp orjakone: ---------- ID: install_httpd_php Function: pkg.installed Result: True Comment: All specified packages are already installed Started: 03:12:05.777863 Duration: 387.502 ms Changes: ---------- ID: check_userdir_status Function: cmd.run Name: a2query -m | grep userdir | grep 'enabled by' &>/dev/null || /usr/sbin/a2enmod userdir Result: True Comment: Command "a2query -m | grep userdir | grep 'enabled by' &>/dev/null || /usr/sbin/a2enmod userdir" run Started: 03:12:06.167690 Duration: 37.4 ms Changes: ---------- pid: 20663 retcode: 0 stderr: stdout: userdir (enabled by site administrator) ---------- ID: execute_userdir_php_script Function: cmd.script Name: salt://1_enable_php-for-userdir.sh Result: True Comment: Command 'salt://1_enable_php-for-userdir.sh' run Started: 03:12:06.206077 Duration: 192.94 ms Changes: ---------- pid: 20690 retcode: 0 stderr: stdout: ---------- ID: add_indexphp_files Function: cmd.script Name: salt://1_create_indexphp.sh Result: True Comment: Command 'salt://1_create_indexphp.sh' run Started: 03:12:06.399689 Duration: 142.251 ms Changes: ---------- pid: 20734 retcode: 0 stderr: stdout: ---------- ID: enable_httpd_php Function: cmd.run Name: /usr/sbin/a2enmod $(a2query -m | awk '{print $1}' | grep php) Result: True Comment: Command "/usr/sbin/a2enmod $(a2query -m | awk '{print $1}' | grep php)" run Started: 03:12:06.542066 Duration: 68.876 ms Changes: ---------- pid: 20741 retcode: 0 stderr: stdout: Considering dependency mpm_prefork for php7.2: Considering conflict mpm_event for mpm_prefork: Considering conflict mpm_worker for mpm_prefork: Module mpm_prefork already enabled Considering conflict php5 for php7.2: Module php7.2 already enabled ---------- ID: httpd_service_restart_php Function: service.running Name: apache2.service Result: True Comment: Service restarted Started: 03:12:06.635009 Duration: 87.188 ms Changes: ---------- apache2.service: True Summary for orjakone ------------ Succeeded: 6 (changed=5) Failed: 0 ------------ Total states run: 6 Total run time: 916.157 ms ``` d) Rakenna tila (state), joka tekee Apachelle uuden nimipohjaisen virtuaalipalvelimen (name based virtual hosting). Voit simuloida nimipalvelun toimintaa hosts-tiedoston avulla. -------------- **Vastaus:** **HUOM!** Tämän olisi voinut tehdä myös luomalla esim. index.html- ja sivustokonfiguraatiotiedostot masterilla, josta ne siirrettäisiin minioneille (file). Nämä määritykset tehdään state-tiedostossa, luonnollisesti. Paljon parempi tapa, jos on esimerkiksi tarkoitus laittaa juuri samansisältöinen _/etc/apache2/sites-available/*.conf_ -tiedosto/template ja samansisältöinen, masterilta päivitettävissä oleva index.html -tiedosto minioneille. Tein nyt huvikseni seuraavalla tavalla, vaikka tiedän, ettei se nyt ihan nappiin menekkään. Luodaan master-koneen */srv/salt/* -kansioon state/konfiguraatiotiedosto *apache_virtualhost_example.sls* sisällöllä: ``` # Author: Pekka Helenius (~Fincer), 2018 ######################################### # Install Apache HTTP daemon to minions install_httpd_daemon: pkg.installed: - pkgs: - apache2 ######################################### copy_httpd_defaultsite: cmd.run: - name: '[ ! -f /etc/apache2/sites-available/$(hostname)-example.conf ] && cd /etc/apache2/sites-available && cp 000-default.conf $(hostname)-example.conf || false' - require: - pkg: install_httpd_daemon create_site_rootdir: cmd.run: - name: /bin/mkdir -p /var/www/html/$(hostname) - require: - pkg: install_httpd_daemon enable_httpd_servername: cmd.run: - name: /bin/sed -i "s/#ServerName www\.example\.com/ServerName $(hostname).example.com/" /etc/apache2/sites-available/$(hostname)-example.conf - require: - cmd: copy_httpd_defaultsite change_defaultsite_root: cmd.run: - name: /bin/sed -i "s/DocumentRoot \/var\/www\/html/DocumentRoot \/var\/www\/html\/$(hostname)/" /etc/apache2/sites-available/$(hostname)-example.conf - require: - cmd: enable_httpd_servername enable_httpd_defaultsite: cmd.run: - name: /usr/sbin/a2ensite $(hostname)-example.conf - require: - cmd: change_defaultsite_root - cmd: copy_httpd_defaultsite - pkg: install_httpd_daemon add_virtualhost_string: cmd.run: - name: /bin/echo "127.0.0.1 $(hostname).example.com" > /etc/hosts - require: - cmd: enable_httpd_defaultsite add_defaultsite_indexfile: cmd.run: - name: '[ ! -f /var/www/html/$(hostname)/index.html ] && /bin/echo "This is default HTML template for $(hostname) ($(hostname).example.com), created on $(date \"+%d-%m-%Y at %X\")" > /var/www/html/$(hostname)/index.html' - require: - cmd: create_site_rootdir - cmd: add_virtualhost_string - cmd: enable_httpd_defaultsite restart_httpd_service: service.running: - name: apache2.service - watch: - cmd: enable_httpd_defaultsite - cmd: add_defaultsite_indexfile ``` Ajetaan em. state masterilta minion-koneelle nimeltä "orjakone" (vain tälle yhdelle koneelle, ei muita orjia nyt!): ``` [10/04/2018 00:13:12 - fincer: ~ ]$ sudo salt 'orjakone' state.apply apache_virtualhost_example orjakone: ---------- ID: install_httpd_daemon Function: pkg.installed Result: True Comment: All specified packages are already installed Started: 05:20:27.160570 Duration: 360.254 ms Changes: ---------- ID: copy_httpd_defaultsite Function: cmd.run Name: [ ! -f /etc/apache2/sites-available/$(hostname)-example.conf ] && cd /etc/apache2/sites-available && cp 000-default.conf $(hostname)-example.conf || false Result: False Comment: Command "[ ! -f /etc/apache2/sites-available/$(hostname)-example.conf ] && cd /etc/apache2/sites-available && cp 000-default.conf $(hostname)-example.conf || false" run Started: 05:20:27.522609 Duration: 4.361 ms Changes: ---------- pid: 22444 retcode: 1 stderr: stdout: ---------- ID: create_site_rootdir Function: cmd.run Name: /bin/mkdir -p /var/www/html/$(hostname) Result: True Comment: Command "/bin/mkdir -p /var/www/html/$(hostname)" run Started: 05:20:27.527146 Duration: 3.26 ms Changes: ---------- pid: 22446 retcode: 0 stderr: stdout: ---------- ID: enable_httpd_servername Function: cmd.run Name: /bin/sed -i "s/#ServerName www\.example\.com/ServerName $(hostname).example.com/" /etc/apache2/sites-available/$(hostname)-example.conf Result: False Comment: One or more requisite failed: apache_virtualhost_example.copy_httpd_defaultsite Changes: ---------- ID: change_defaultsite_root Function: cmd.run Name: /bin/sed -i "s/DocumentRoot \/var\/www\/html/DocumentRoot \/var\/www\/html\/$(hostname)/" /etc/apache2/sites-available/$(hostname)-example.conf Result: False Comment: One or more requisite failed: apache_virtualhost_example.enable_httpd_servername Changes: ---------- ID: enable_httpd_defaultsite Function: cmd.run Name: /usr/sbin/a2ensite $(hostname)-example.conf Result: False Comment: One or more requisite failed: apache_virtualhost_example.copy_httpd_defaultsite, apache_virtualhost_example.change_defaultsite_root Changes: ---------- ID: add_virtualhost_string Function: cmd.run Name: /bin/echo "127.0.0.1 $(hostname).example.com" > /etc/hosts Result: False Comment: One or more requisite failed: apache_virtualhost_example.enable_httpd_defaultsite Changes: ---------- ID: add_defaultsite_indexfile Function: cmd.run Name: [ ! -f /var/www/html/$(hostname)/index.html ] && /bin/echo "This is default HTML template for $(hostname) ($(hostname).example.com), created on $(date \"+%d-%m-%Y at %X\")" > /var/www/html/$(hostname)/index.html Result: False Comment: One or more requisite failed: apache_virtualhost_example.add_virtualhost_string, apache_virtualhost_example.enable_httpd_defaultsite Changes: ---------- ID: restart_httpd_service Function: service.running Name: apache2.service Result: False Comment: One or more requisite failed: apache_virtualhost_example.add_defaultsite_indexfile, apache_virtualhost_example.enable_httpd_defaultsite Changes: Summary for orjakone ------------ Succeeded: 2 (changed=2) Failed: 7 ------------ Total states run: 9 Total run time: 367.875 ms ``` Hups! Epäonnistumisia, emämunaus. Ihan odotettua, sillä... ...epäonnistumiset johtuvat siitä, että olen määritellyt tietyt ID:t, kuten tässä tapauksessa ehkä kriittisimpänä copy_httpd_defaultsite:n, palauttamaan komennon suorittamisesta arvon false, mikäli mm. tiedosto $(hostname)-example.conf on jo olemassa. Koska kyseinen ID on riippuvuutena alemmille ID:ille, ja nämä ID:t edelleen riippuvuutena eteenpäin muille ID:lle, syntyy ketjureaktio, jossa epäonnistuneita tiloja tulee suuri määrä. Tässä tapauksessa 7 kpl. Tulos oli odotettu _tässä konfiguraatiossa_. Orjakoneen selainnäkymässä (*xdg-open http://$(hostname).example.com*) ajettuna lopputulos näyttää tältä: ![minion-virtualhost](https://raw.githubusercontent.com/Fincer-altego/central-management-of-multiple-servers/master/images/minion-example.png) e) Tee tila, joka laittaa esimerkkikotisivun uusille käyttäjille. Voit laittaa esimerkkikotisivu /etc/skel/:iin, niin se tulee automaattisesti ‘adduser tero’ komennolla käyttäjiä luodessa. -------------- **Vastaus:** **HUOM!** Tämä on osittain tehtynä jo vastauksissa b) ja c) (Mitä on tehty: On luotu jokaiselle käyttäjälle index.html (b) ja PHP:n kytkemisen yhteydessä index.php (c)) **HUOM!** Tässä olisi voinut hyödyntää esim. kansiorakennetta _/srv/salt/apache_, jonne laitettu state-tiedostot. Nyt toimitaan vielä yksinkertaisemmalla pohjalla, minkä takia state-tiedostoissa esiintyy päällekkäisyyttä. Monimutkaisemmissa konfiguraatioissa puu-rakennetta olisi hyvä harkita (mandatory?). Lisätään state *2_apache_skelsite.sls*, joka lisää esimerkkikotisivun määriteltyjen minion-koneiden hakemistoon _/etc/skel_ (teemme alihakemiston *public_html* tänne state-tiedostossa...): ``` # Author: Pekka Helenius (~Fincer), 2018 ######################################### # Install Apache HTTP daemon to minions install_httpd_daemon: pkg.installed: - pkgs: - apache2 ######################################### # Enable Apache userdir module httpd_userdir: cmd.run: - name: /usr/sbin/a2enmod userdir - require: - pkg: install_httpd_daemon ######################################### # Replace default index.html content httpd_foo-index: cmd.run: - name: /bin/echo "foo" > /var/www/html/index.html - require: - cmd: httpd_userdir - pkg: install_httpd_daemon ######################################### # Restart Apache HTTP daemon httpd_service_restart_skelsite: service.running: - name: apache2.service - watch: - cmd: httpd_userdir ######################################### # Create /etc/skel/public_html apache_add_skel_html_dir: cmd.run: - name: /bin/mkdir -p /etc/skel/public_html - require: - service: httpd_service_restart_skelsite ######################################### # Add index.html apache_default_userindex_file: cmd.run: - name: /bin/echo "Empty HTML template" > /etc/skel/public_html/index.html - require: - cmd: apache_add_skel_html_dir ``` Master-koneen output: ``` [10/04/2018 01:15:01 - fincer: ~ ]$ sudo salt 'orjakone' state.apply 2_apache_skelsite orjakone: ---------- ID: install_httpd_daemon Function: pkg.installed Result: True Comment: All specified packages are already installed Started: 03:46:46.743389 Duration: 368.537 ms Changes: ---------- ID: httpd_userdir Function: cmd.run Name: /usr/sbin/a2enmod userdir Result: True Comment: Command "/usr/sbin/a2enmod userdir" run Started: 03:46:47.113788 Duration: 21.611 ms Changes: ---------- pid: 21155 retcode: 0 stderr: stdout: Module userdir already enabled ---------- ID: httpd_foo-index Function: cmd.run Name: /bin/echo "foo" > /var/www/html/index.html Result: True Comment: Command "/bin/echo "foo" > /var/www/html/index.html" run Started: 03:46:47.135793 Duration: 4.274 ms Changes: ---------- pid: 21160 retcode: 0 stderr: stdout: ---------- ID: httpd_service_restart_skelsite Function: service.running Name: apache2.service Result: True Comment: Service restarted Started: 03:46:47.161935 Duration: 103.555 ms Changes: ---------- apache2.service: True ---------- ID: apache_add_skel_html_dir Function: cmd.run Name: /bin/mkdir -p /etc/skel/public_html Result: True Comment: Command "/bin/mkdir -p /etc/skel/public_html" run Started: 03:46:47.265901 Duration: 73.066 ms Changes: ---------- pid: 21178 retcode: 0 stderr: stdout: ---------- ID: apache_default_userindex_file Function: cmd.run Name: /bin/echo "Empty HTML template" > /etc/skel/public_html/index.html Result: True Comment: Command "/bin/echo "Empty HTML template" > /etc/skel/public_html/index.html" run Started: 03:46:47.341257 Duration: 13.803 ms Changes: ---------- pid: 21185 retcode: 0 stderr: stdout: Summary for orjakone ------------ Succeeded: 6 (changed=5) Failed: 0 ------------ Total states run: 6 Total run time: 584.846 ms ``` Minion-koneelta tarkistusta (master-koneella katsottuna): ``` [10/04/2018 02:54:51 - fincer: ~ ]$ sudo salt 'orjakone' cmd.run '/bin/ls /etc/skel && [ -d /etc/skel/public_html ] && /bin/cat /etc/skel/public_html/*' orjakone: index.html public_html Empty HTML template ``` f) Eri asetukset. Tee Package-File-Service tilalla eri asetuksia kuin ne, mitä tehtiin tunnilla; ja eri kuin mitä teit/teet h2 muissa kohdissa. Voit muuttaa jotain toista asetusta samoista demoneista tai valita kokonaan eri demonit. -------------- **Vastaus:** Toteutetaan Knock daemonin (knockd - small port-knock daemon) -asennus. Luodaan master-koneelle tiedosto */srv/salt/knockd.conf*, joka annetaan valituille minioneille (asennetaan polkuun */etc/knockd.conf*) Haluttu *knockd.conf*:n sisältö (_/srv/salt/knockd.conf_): ``` [options] UseSyslog [openSSH] sequence = tcp:7065,udp:2431,tcp:421,tcp:4113 seq_timeout = 5 command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn [closeSSH] sequence = tcp:4113,tcp:421,udp:2431,tcp:7065 seq_timeout = 5 command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn ``` Luodaan master-koneelle state-tiedosto _/srv/salt/install_knockd.sls_: ``` # Author: Pekka Helenius (~Fincer), 2018 ######################################### # Install Knock daemon to minions check_ssh: pkg.installed: - pkgs: - ssh install_knockd: pkg.installed: - pkgs: - knockd # Deliver Knock daemon configuration file to minions deliver_knockd-conf: file.managed: - name: /etc/knockd.conf - user: root - group: root - mode: 644 - source: salt://knockd.conf - require: - pkg: install_knockd # Do not proceed if any SSH sessions are open in minion's side. This is just to avoid any harmful effects prevent_if_ssh_sessions_open: cmd.run: - name: 'if [ $(/bin/netstat -tnpa | grep "ESTABLISHED.*sshd" | wc -l) -gt 0 ]; then false; fi' - require: - pkg: check_ssh # PROCEED ONLY IF NO SSH SESSIONS ARE OPEN # # Drop SSH port connections. Use port which is defined in minion's /etc/ssh/sshd_config file drop_ssh_port: cmd.run: - name: /sbin/iptables -A INPUT -p tcp --dport $(grep -E ^[#P]+ort /etc/ssh/sshd_config | awk '{print $2}') -j DROP - require: - cmd: prevent_if_ssh_sessions_open - pkg: check_ssh - file: deliver_knockd-conf # Change default SSH port 22 in minion's /etc/knockd.conf file: post-configure_knockd-conf: cmd.run: - name: /bin/sed -i "s/dport 22/dport $(grep -E ^[#P]+ort /etc/ssh/sshd_config | awk '{print $2}')/" /etc/knockd.conf - require: - pkg: check_ssh - file: deliver_knockd-conf # Enable knockd daemon enable_knockd_service: cmd.run: - name: /bin/systemctl enable knockd.service - require: - pkg: install_knockd # Restart knockd daemon restart_knockd_service: service.running: - name: knockd.service - watch: - cmd: post-configure_knockd-conf ``` Esimerkki-output master-koneella ajettuna: ``` [10/04/2018 06:17:11 - fincer: ~ ]$ sudo salt 'orjakone' state.apply install_knockd orjakone: ---------- ID: check_ssh Function: pkg.installed Result: True Comment: All specified packages are already installed Started: 06:25:12.849731 Duration: 366.695 ms Changes: ---------- ID: install_knockd Function: pkg.installed Result: True Comment: The following packages were installed/updated: knockd Started: 06:25:13.216541 Duration: 53498.645 ms Changes: ---------- knockd: ---------- new: 0.7-1ubuntu1 old: ---------- ID: deliver_knockd-conf Function: file.managed Name: /etc/knockd.conf Result: True Comment: File /etc/knockd.conf updated Started: 06:26:06.717147 Duration: 17.544 ms Changes: ---------- diff: --- +++ @@ -1,15 +1,14 @@ [options] - UseSyslog + UseSyslog [openSSH] - sequence = 7000,8000,9000 - seq_timeout = 5 - command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT - tcpflags = syn + sequence = tcp:7065,udp:2431,tcp:421,tcp:4113 + seq_timeout = 5 + command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT + tcpflags = syn [closeSSH] - sequence = 9000,8000,7000 - seq_timeout = 5 - command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT - tcpflags = syn - + sequence = tcp:4113,tcp:421,udp:2431,tcp:7065 + seq_timeout = 5 + command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT + tcpflags = syn ---------- ID: prevent_if_ssh_sessions_open Function: cmd.run Name: if [ $(/bin/netstat -tnpa | grep "ESTABLISHED.*sshd" | wc -l) -gt 0 ]; then false; fi Result: True Comment: Command "if [ $(/bin/netstat -tnpa | grep "ESTABLISHED.*sshd" | wc -l) -gt 0 ]; then false; fi" run Started: 06:26:06.735404 Duration: 59.527 ms Changes: ---------- pid: 23916 retcode: 0 stderr: stdout: ---------- ID: drop_ssh_port Function: cmd.run Name: /sbin/iptables -A INPUT -p tcp --dport $(grep -E ^[#P]+ort /etc/ssh/sshd_config | awk '{print $2}') -j DROP Result: True Comment: Command "/sbin/iptables -A INPUT -p tcp --dport $(grep -E ^[#P]+ort /etc/ssh/sshd_config | awk '{print $2}') -j DROP" run Started: 06:26:06.795619 Duration: 457.367 ms Changes: ---------- pid: 23927 retcode: 0 stderr: stdout: ---------- ID: post-configure_knockd-conf Function: cmd.run Name: /bin/sed -i "s/dport 22/dport $(grep -E ^[#P]+ort /etc/ssh/sshd_config | awk '{print $2}')/" /etc/knockd.conf Result: True Comment: Command "/bin/sed -i "s/dport 22/dport $(grep -E ^[#P]+ort /etc/ssh/sshd_config | awk '{print $2}')/" /etc/knockd.conf" run Started: 06:26:07.253529 Duration: 16.545 ms Changes: ---------- pid: 23963 retcode: 0 stderr: stdout: ---------- ID: enable_knockd_service Function: cmd.run Name: /bin/systemctl enable knockd.service Result: True Comment: Command "/bin/systemctl enable knockd.service" run Started: 06:26:07.270551 Duration: 539.568 ms Changes: ---------- pid: 23968 retcode: 0 stderr: stdout: ---------- ID: restart_knockd_service Function: service.running Name: knockd.service Result: True Comment: Started Service knockd.service Started: 06:26:08.461999 Duration: 168.812 ms Changes: ---------- knockd.service: True Summary for orjakone ------------ Succeeded: 8 (changed=7) Failed: 0 ------------ Total states run: 8 Total run time: 55.125 s ``` Esimerkkikuva minion-koneen Knock daemonin konfiguraatiotiedostosta, jossa on vaihdettu porttinumero sen mukaan kuin se on määritelty minion-koneen SSH-asetuksissa: ![minion-knockd-sample](https://raw.githubusercontent.com/Fincer-altego/central-management-of-multiple-servers/master/images/minion-knockd-example.png)