# Pengamanan Server



# Pengamanan Server Menggunakan Fail2Ban

Fail2Ban disini ditujukan untuk memblokir IP client yang melakukan aktivitas berbahaya pada aplikasi/website pada server.

**Installasi:**  
`sudo apt install fail2ban`

**Konfigurasi Dasar untuk SSH**  
`sudo nano /etc/fail2ban/jail.local`

**isi:**  
<span style="color: rgb(224, 62, 45);">\[sshd\]</span>  
<span style="color: rgb(224, 62, 45);">enabled = true</span>  
<span style="color: rgb(224, 62, 45);">port = ssh</span>  
<span style="color: rgb(224, 62, 45);">filter = sshd</span>  
<span style="color: rgb(224, 62, 45);">logpath = /var/log/auth.log</span>  
<span style="color: rgb(224, 62, 45);">maxretry = 5</span>  
<span style="color: rgb(224, 62, 45);">bantime = 1h</span>  
<span style="color: rgb(224, 62, 45);">findtime = 10m</span>

<span style="color: rgb(224, 62, 45);">\[apache-auth\]</span>  
<span style="color: rgb(224, 62, 45);">enabled = true</span>  
<span style="color: rgb(224, 62, 45);">port = http,https</span>  
<span style="color: rgb(224, 62, 45);">logpath = /var/log/apache\*/\*error.log</span>  
<span style="color: rgb(224, 62, 45);">maxretry = 5</span>

**Restart Fail2Ban**  
`sudo systemctl restart fail2ban`  
sudo systemctl enable fail2ban

**Cek Status Jail**  
`sudo fail2ban-client status`

Metode pengamanan paling baik dengan Fail2Ban adalah dengan menyesuaikan perilaku atau aktivitas client dalam mengakses aplikasi/website pada server. Cara mudahnya adalah melihat error yang dihasil pada tail -f /var/log/apache2/error.log.

Dari error.log tersebut dihasilkan informasi aktivitas client yang melakukan upaya berbahaya yang menghasilkan error pada server apache.

Sebagai contoh saya mau memblokir IP client dengan aktivitas error berikut:  
\\\[Fri May 16 19:32:01.013545 2025\] \\\[proxy\\\_fcgi\\:error\] \\\[pid 1496923\] \\\[client 159.65.1.31:55208\] AH01071: Got error 'PHP message: PHP Warning: Constant WP\\\_MEMORY\\\_LIMIT already defined in /var/www/html/dpmdsos/public\\\_html/wp-config.php on line 98' \\\[Fri May 16 19:32:01.330516 2025\] \\\[proxy\\\_fcgi\\:error\] \\\[pid 1496903\] \\\[client 159.65.1.31:55174\] AH01071: Got error 'PHP message: PHP Warning: The magic method Vc\\\_Manager::\\\_\\\_wakeup() must have public visibility in /var/www/html/dpupkp/public\\\_html/wp-content/plugins/js\\\_composer/include/classes/core/class-vc-manager.php on line 203' \\\[Fri May 16 19:32:01.505303 2025\] \\\[proxy\\\_fcgi\\:error\] \\\[pid 1496930\] \\\[client 159.65.1.31:55479\] AH01071: Got error 'PHP message: PHP Warning: Constant WP\\\_MEMORY\\\_LIMIT already defined in /var/www/html/dpmdsos/public\\\_html/wp-config.php on line 98' \\\[Fri May 16 19:32:01.726184 2025\] \\\[proxy\\\_fcgi\\:error\] \\\[pid 1497083\] \\\[client 159.65.1.31:55322\] AH01071: Got error 'PHP message: PHP Warning: The magic method Vc\\\_Manager::\\\_\\\_wakeup() must have public visibility in /var/www/html/disperpusip/public\\\_html/wp-content/plugins/js\\\_composer/include/classes/core/class-vc-manager.php on line 203' \\\[Fri May 16 19:32:01.773397 2025\] \\\[autoindex\\:error\] \\\[pid 1487621\] \\\[client 209.38.120.221:57305\] AH01276: Cannot serve directory /var/www/html/inspektorat/public\\\_html/.well-known/: No matching DirectoryIndex (index.html,index.cgi,index.pl,index.php,index.xhtml,index.htm) found, and server-generated directory index forbidden by Options directive \\\[Fri May 16 19:32:01.836303 2025\] \\\[autoindex\\:error\] \\\[pid 1487621\] \\\[client 209.38.120.221:57305\] AH01276: Cannot serve directory /var/www/html/inspektorat/public\\\_html/.well-known/pki-validation/: No matching DirectoryIndex (index.html,index.cgi,index.pl,index.php,index.xhtml,index.htm) found, and server-generated directory index forbidden by Options directive \\\[Fri May 16 19:32:01.907570 2025\] \\\[autoindex\\:error\] \\\[pid 1487621\] \\\[client 209.38.120.221:57305\] AH01276: Cannot serve directory /var/www/html/inspektorat/public\\\_html/.well-known/acme-challenge/: No matching DirectoryIndex (index.html,index.cgi,index.pl,index.php,index.xhtml,index.htm) found, and server-generated directory index forbidden by Options directive

maka saya membuat file filter baru di `nano /etc/fail2ban/filter.d/apache-php-errors.conf`

<span style="color: rgb(35, 111, 161);">**<span style="color: rgb(0, 0, 0);">isi:</span>**  
\[Definition\]</span>  
<span style="color: rgb(35, 111, 161);">failregex = ^\\\[\[^\\\]\]\*\\\] \\\[\[^\\\]\]\*\\\] \\\[pid \[0-9\]\*\\\] \\\[client &lt;HOST&gt;:\[0-9\]\*\\\] AH01071: Got error 'PHP message: PHP Warning:.\*$</span>  
<span style="color: rgb(35, 111, 161);"> ^\\\[\[^\\\]\]\*\\\] \\\[autoindex:error\\\] \\\[pid \[0-9\]\*\\\] \\\[client &lt;HOST&gt;:\[0-9\]\*\\\] AH01276: Cannot serve directory.\*$</span>  
<span style="color: rgb(35, 111, 161);">ignoreregex =</span>

***<span style="color: rgb(0, 0, 0);">Note: gunakan Chatgpt atau Deepseek untuk membuat koding filter</span>***

<span style="color: rgb(0, 0, 0);">Kemudian tambahkan jail baru di `/etc/fail2ban/jail.local`  
</span>

Isi:  
<span style="color: rgb(224, 62, 45);">\[apache-php-errors\]</span>  
<span style="color: rgb(224, 62, 45);">enabled = true</span>  
<span style="color: rgb(224, 62, 45);">port = http,https</span>  
<span style="color: rgb(224, 62, 45);">filter = apache-php-errors</span>  
<span style="color: rgb(224, 62, 45);">logpath = /var/log/apache2/error.log</span>  
<span style="color: rgb(224, 62, 45);">maxretry = 5</span>  
<span style="color: rgb(224, 62, 45);">findtime = 10m</span>  
<span style="color: rgb(224, 62, 45);">bantime = 1h</span>

Restart Fail2Ban  
`sudo systemctl restart fail2ban`

Kemudian cek untuk melihat IP client sudah diblokir   
`sudo fail2ban-client status apache-php-errors`

Silahkan tambahkan lagi filter lainnya sesuai dengan error.log yang diperoleh.

Apabila suatu waktu anda pun tidak dapat mengakses aplikasi/website pada server anda. Maka ada kemungkinan anda pun juga sudah diblokir oleh filter Fail2Ban yang anda buat sendiri. Maka kerjakan Tips berikut jika terjadi.

sudo fail2ban-client status &lt;nama\_jail&gt;  
\# Contoh:  
`sudo fail2ban-client status <span style="color: rgb(224, 62, 45);">apache-php-errors</span>`

Jika dipastikan memang IP anda yang diblokir maka lakukan seperti contoh berikut:  
`sudo fail2ban-client set apache-wp-warnings unbanip 36.75.65.41`

dan cara paling aman adalah dengan membuat **Whitelist IP Anda** di `nano /etc/fail2ban/jail.local`  
Isi:  
<span style="color: rgb(224, 62, 45);">\[DEFAULT\]</span>  
<span style="color: rgb(224, 62, 45);">ignoreip = 127.0.0.1/8 ::1 36.75.65.41</span>

atau kurangi agresivitas jail:

<span style="color: rgb(224, 62, 45);">\[apache-php-errors\]</span>  
<span style="color: rgb(224, 62, 45);">enabled = true</span>  
<span style="color: rgb(224, 62, 45);">port = http,https</span>  
<span style="color: rgb(224, 62, 45);">filter = apache-php-errors</span>  
<span style="color: rgb(224, 62, 45);">logpath = /var/log/apache2/error.log</span>  
<span style="color: rgb(224, 62, 45);">maxretry = 10 #ubah dari 5 jadi 10</span>  
<span style="color: rgb(224, 62, 45);">findtime = 30m #ubah dari 10 jadi 30</span>  
<span style="color: rgb(224, 62, 45);">bantime = 1h #ubah dari 24h jadi 1h</span>

Lakukan Monitoring lol Fail2Ban:

`sudo tail -f /var/log/fail2ban.log`

Cek daftar IP yang sudah diblokir fail2ban:

`for jail in $(fail2ban-client status | grep 'Jail list' | cut -d: -f2 | tr ',' '\n' | tr -d ' '); do    echo "== Jail: $jail ==";    fail2ban-client status "$jail" | grep 'Banned IP list';    echo;done`

Buka semua IP yang diblokir ada filter fail2ban:

  
  
`for jail in $(fail2ban-client status | grep 'Jail list:' | cut -d: -f2 | tr -d ' ' | tr ',' ' '); do  echo "Checking jail: $jail"  banned_ips=$(fail2ban-client status "$jail" | grep 'Banned IP list' | cut -d: -f2)  for ip in $banned_ips; do    fail2ban-client set "$jail" unbanip "$ip" && echo "→ Unbanned $ip from $jail"  donedone`

Buka Blokir khusus Jail tertentu. ini misalnya modsecurity-aggressive:

`for ip in $(sudo fail2ban-client status modsecurity-aggressive | grep 'Banned IP list:' | awk -F': ' '{print $2}'); do    sudo fail2ban-client set modsecurity-aggressive unbanip $ipdone`

Cara Membuka blokir IP tertentu pada semua jail:

`IP="182.8.131.150"```

`for jail in $(fail2ban-client status | grep 'Jail list:' | cut -d: -f2 | tr -d ' ' | tr ',' ' '); do  echo "Checking jail: $jail"  if fail2ban-client status "$jail" | grep -q "$IP"; then    fail2ban-client set "$jail" unbanip "$IP" && echo "→ Unbanned $IP from $jail"  else    echo "No ban for $IP in $jail"  fidone`

# App Logwebmin

Aplikasi ini adalah hasil pengembangan mandiri Dinas Kominfo Bartim untuk memonitoring dan memblokir aktivitas client yang mencurigakan pada server webmin (server apache).

[![image.png](https://dokumen.baritotimurkab.go.id/uploads/images/gallery/2025-05/scaled-1680-/C5jx2dzf6eHZWzIq-image.png)](https://dokumen.baritotimurkab.go.id/uploads/images/gallery/2025-05/C5jx2dzf6eHZWzIq-image.png)

[![image.png](https://dokumen.baritotimurkab.go.id/uploads/images/gallery/2025-05/scaled-1680-/8i8cKmlIzcEyqXHL-image.png)](https://dokumen.baritotimurkab.go.id/uploads/images/gallery/2025-05/8i8cKmlIzcEyqXHL-image.png)

**Apikasi ini telah diinstall pada server Apache dengan spesifikasi:**

<div class="right-aligned" id="bkmrk--2"></div>1. <div class="right-aligned">CPU 8x Intel(R) Xeon(R) Bronze 3206R CPU @ 1.90GHz (1 Socket)</div>
2. RAM 32 GB
3. HDD 100GB
4. OS <span data-id="sysinfo_os">Linux Mint 20.2</span>

Aplikasi dapat diunduh pada link [**Cloud Repositori Bartim**.](https://drive.baritotimurkab.go.id/index.php/s/3FPMdLWejnB6HW5)

**Petunjuk Instalasi:**

1\. Upload file aplikasi pada /var/www/html/logwebmin

2\. Buat konfigurasi virtual domain pada /etc/apache2/sites-available/000-default.conf

<div id="bkmrk-%3Cvirtualhost-%2A%3A80%3E"><span style="color: rgb(224, 62, 45);">&lt;VirtualHost \*:80&gt;</span></div><div id="bkmrk-%C2%A0-%C2%A0-servername-log6."><span style="color: rgb(224, 62, 45);"> ServerName log6.baritotimurkab.go.id</span></div><div id="bkmrk-%C2%A0-%C2%A0-documentroot-%2Fva"><span style="color: rgb(224, 62, 45);"> DocumentRoot /var/www/html/logwebmin/public</span></div><div id="bkmrk--3"></div><div id="bkmrk-%C2%A0-%C2%A0-rewriteengine-on"><span style="color: rgb(224, 62, 45);"> RewriteEngine on</span></div><div id="bkmrk-%C2%A0-%C2%A0-documentroot-%2Fva-1"><span style="color: rgb(224, 62, 45);"> DocumentRoot /var/www/html/logwebmin/public</span></div><div id="bkmrk-%C2%A0-%C2%A0-rewritecond-%25%7Bse"><span style="color: rgb(224, 62, 45);"> RewriteCond %{SERVER\_NAME} =www.log6.baritotimurkab.go.id \[OR\]</span></div><div id="bkmrk-%C2%A0-%C2%A0-rewritecond-%25%7Bse-1"><span style="color: rgb(224, 62, 45);"> RewriteCond %{SERVER\_NAME} =log6.baritotimurkab.go.id</span></div><div id="bkmrk-%C2%A0-%C2%A0-rewriterule-%5E-ht"><span style="color: rgb(224, 62, 45);"> RewriteRule ^ https://%{SERVER\_NAME}%{REQUEST\_URI} \[END,NE,R=permanent\]</span></div><div id="bkmrk-%3C%2Fvirtualhost%3E"><span style="color: rgb(224, 62, 45);">&lt;/VirtualHost&gt;</span></div><div id="bkmrk--4">  
</div><div id="bkmrk--5"></div><div id="bkmrk--6"></div>3\. Buat ssl dengan letsencrypt

4\. Buat konfigurasi virtual domain ssl pada /etc/apache2/sites-available/default-ssl.conf

<div id="bkmrk-%3Cifmodule-mod_ssl.c%3E"><span style="color: rgb(224, 62, 45);">&lt;IfModule mod\_ssl.c&gt;</span></div><div id="bkmrk-%3Cvirtualhost-%2A%3A443%3E"><span style="color: rgb(224, 62, 45);">&lt;VirtualHost \*:443&gt;</span></div><div id="bkmrk-%C2%A0-%C2%A0-servername-log6.-1"><span style="color: rgb(224, 62, 45);"> ServerName log6.baritotimurkab.go.id</span></div><div id="bkmrk-%C2%A0-%C2%A0-documentroot-%2Fva-2"><span style="color: rgb(224, 62, 45);"> DocumentRoot /var/www/html/logwebmin/public</span></div><div id="bkmrk--7">  
</div><div id="bkmrk-%C2%A0-%C2%A0-sslengine-on"><span style="color: rgb(224, 62, 45);"> SSLEngine on</span></div><div id="bkmrk-%C2%A0-%C2%A0-sslcertificatefi"><span style="color: rgb(224, 62, 45);"> SSLCertificateFile /etc/letsencrypt/live/log6.baritotimurkab.go.id/fullchain.pem</span></div><div id="bkmrk-%C2%A0-%C2%A0-sslcertificateke"><span style="color: rgb(224, 62, 45);"> SSLCertificateKeyFile /etc/letsencrypt/live/log6.baritotimurkab.go.id/privkey.pem</span></div><div id="bkmrk-%C2%A0-%C2%A0-include-%2Fetc%2Flet"><span style="color: rgb(224, 62, 45);"> Include /etc/letsencrypt/options-ssl-apache.conf</span></div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0%C2%A0"><span style="color: rgb(224, 62, 45);"> </span></div><div id="bkmrk-%C2%A0-%C2%A0-errorlog-%24%7Bapach"><span style="color: rgb(224, 62, 45);"> ErrorLog ${APACHE\_LOG\_DIR}/logwebmin\_error.log</span></div><div id="bkmrk-%C2%A0-%C2%A0-customlog-%24%7Bapac"><span style="color: rgb(224, 62, 45);"> CustomLog ${APACHE\_LOG\_DIR}/logwebmin\_access.log combined</span></div><div id="bkmrk-%3C%2Fvirtualhost%3E-1"><span style="color: rgb(224, 62, 45);">&lt;/VirtualHost&gt;</span></div><div id="bkmrk-%3C%2Fifmodule%3E"><span style="color: rgb(224, 62, 45);">&lt;/IfModule&gt;</span></div><div id="bkmrk--8"></div><div id="bkmrk--9"></div><div id="bkmrk--10"></div><div id="bkmrk--11"></div><div id="bkmrk--12"></div><div id="bkmrk--13"></div><div id="bkmrk--14"></div><div id="bkmrk-5.-buat-inisiasi-fit">  
5. Buat inisiasi fitur socket</div><div id="bkmrk--15"></div><div id="bkmrk-nano-%2Fetc%2Fsystemd%2Fsy">**nano /etc/systemd/system/ipblock.service**</div><div id="bkmrk-isi%3A">isi:</div><span style="color: rgb(224, 62, 45);">\[Unit\]</span>  
<span style="color: rgb(224, 62, 45);">Description=IP Blocking Service</span>  
<span style="color: rgb(224, 62, 45);">Requires=ipblock.socket</span>

<span style="color: rgb(224, 62, 45);">\[Service\]</span>  
<span style="color: rgb(224, 62, 45);">Type=simple</span>  
<span style="color: rgb(224, 62, 45);">ExecStart=/usr/local/bin/ipblock-daemon</span>  
<span style="color: rgb(224, 62, 45);">User=www-data</span>  
<span style="color: rgb(224, 62, 45);">Group=www-data</span>  
<span style="color: rgb(224, 62, 45);">Restart=always</span>  
<span style="color: rgb(224, 62, 45);">RestartSec=5</span>  
<span style="color: rgb(224, 62, 45);">Environment="SOCKET\_PATH=/var/www/html/logwebmin/storage/sockets/ipblock.sock"</span>

<span style="color: rgb(224, 62, 45);">\[Install\]</span>  
<span style="color: rgb(224, 62, 45);">WantedBy=multi-user.target</span>

**nano /etc/systemd/system/ipblock.socket**  
isi:  
<span style="color: rgb(224, 62, 45);">\[Unit\]</span>

<span style="color: rgb(224, 62, 45);">Description=IP Blocking Socket</span>

<span style="color: rgb(224, 62, 45);">\[Socket\]</span>  
<span style="color: rgb(224, 62, 45);">ListenStream=/var/www/html/logwebmin/storage/sockets/ipblock.sock</span>  
<span style="color: rgb(224, 62, 45);">SocketUser=www-data</span>  
<span style="color: rgb(224, 62, 45);">SocketGroup=www-data</span>  
<span style="color: rgb(224, 62, 45);">SocketMode=0660</span>

<span style="color: rgb(224, 62, 45);">\[Install\]</span>  
<span style="color: rgb(224, 62, 45);">WantedBy=sockets.target</span>

**nano /usr/local/bin/ipblock-daemon** (berikan permissions 0755 dan ownership www-data)  
isi:  
<span style="color: rgb(224, 62, 45);">\#!/usr/bin/python3</span>

<span style="color: rgb(224, 62, 45);">import socket</span>  
<span style="color: rgb(224, 62, 45);">import os</span>  
<span style="color: rgb(224, 62, 45);">import subprocess</span>  
<span style="color: rgb(224, 62, 45);">import re</span>

<span style="color: rgb(224, 62, 45);">SOCKET\_PATH = '/var/www/html/logwebmin/storage/sockets/ipblock.sock'</span>

<span style="color: rgb(224, 62, 45);">\# Setup socket directory</span>  
<span style="color: rgb(224, 62, 45);">os.makedirs(os.path.dirname(SOCKET\_PATH), exist\_ok=True)</span>

<span style="color: rgb(224, 62, 45);">\# Remove old socket if exists</span>  
<span style="color: rgb(224, 62, 45);">try:</span>  
<span style="color: rgb(224, 62, 45);"> os.unlink(SOCKET\_PATH)</span>  
<span style="color: rgb(224, 62, 45);">except FileNotFoundError:</span>  
<span style="color: rgb(224, 62, 45);"> pass</span>

<span style="color: rgb(224, 62, 45);">\# Create and bind socket</span>  
<span style="color: rgb(224, 62, 45);">sock = socket.socket(socket.AF\_UNIX, socket.SOCK\_STREAM)</span>  
<span style="color: rgb(224, 62, 45);">sock.bind(SOCKET\_PATH)</span>  
<span style="color: rgb(224, 62, 45);">sock.listen(1)</span>  
<span style="color: rgb(224, 62, 45);">os.chmod(SOCKET\_PATH, 0o660)</span>  
<span style="color: rgb(224, 62, 45);">os.chown(SOCKET\_PATH, 33, 33) # www-data user and group ID</span>

<span style="color: rgb(224, 62, 45);">def validate\_ip(ip):</span>  
<span style="color: rgb(224, 62, 45);"> """Validate IPv4 address format"""</span>  
<span style="color: rgb(224, 62, 45);"> pattern = r'^(25\[0-5\]|2\[0-4\]\[0-9\]|\[01\]?\[0-9\]\[0-9\]?)\\.(25\[0-5\]|2\[0-4\]\[0-9\]|\[01\]?\[0-9\]\[0-9\]?)\\.(25\[0-5\]|2\[0-4\]\[0-9\]|\[01\]?\[0-9\]\[0-9\]?)\\.(25\[0-5\]|2\[0-4\]\[0-9\]|\[01\]?\[0-9\]\[0-9\]?)$'</span>  
<span style="color: rgb(224, 62, 45);"> return re.match(pattern, ip) is not None</span>

<span style="color: rgb(224, 62, 45);">while True:</span>  
<span style="color: rgb(224, 62, 45);"> conn, \_ = sock.accept()</span>  
<span style="color: rgb(224, 62, 45);"> try:</span>  
<span style="color: rgb(224, 62, 45);"> data = conn.recv(1024).decode().strip()</span>  
<span style="color: rgb(224, 62, 45);"> if not data:</span>  
<span style="color: rgb(224, 62, 45);"> continue</span>  
<span style="color: rgb(224, 62, 45);"> </span>  
<span style="color: rgb(224, 62, 45);"> # Handle unblock command</span>  
<span style="color: rgb(224, 62, 45);"> if data.startswith('unblock:'):</span>  
<span style="color: rgb(224, 62, 45);"> ip = data.split(':')\[1\]</span>  
<span style="color: rgb(224, 62, 45);"> if validate\_ip(ip):</span>  
<span style="color: rgb(224, 62, 45);"> try:</span>  
<span style="color: rgb(224, 62, 45);"> subprocess.run(\['sudo', '/usr/local/bin/unblock-ip.sh', ip\], check=True)</span>  
<span style="color: rgb(224, 62, 45);"> conn.send(b"OK")</span>  
<span style="color: rgb(224, 62, 45);"> except subprocess.CalledProcessError as e:</span>  
<span style="color: rgb(224, 62, 45);"> conn.send(f"ERROR: Unblock failed - {str(e)}".encode())</span>  
<span style="color: rgb(224, 62, 45);"> else:</span>  
<span style="color: rgb(224, 62, 45);"> conn.send(b"ERROR: Invalid IP format for unblock")</span>  
<span style="color: rgb(224, 62, 45);"> </span>  
<span style="color: rgb(224, 62, 45);"> # Handle block command (original functionality)</span>  
<span style="color: rgb(224, 62, 45);"> else:</span>  
<span style="color: rgb(224, 62, 45);"> ip = data</span>  
<span style="color: rgb(224, 62, 45);"> if validate\_ip(ip):</span>  
<span style="color: rgb(224, 62, 45);"> try:</span>  
<span style="color: rgb(224, 62, 45);"> subprocess.run(\['sudo', '/usr/local/bin/block-ip.sh', ip\], check=True)</span>  
<span style="color: rgb(224, 62, 45);"> conn.send(b"OK")</span>  
<span style="color: rgb(224, 62, 45);"> except subprocess.CalledProcessError as e:</span>  
<span style="color: rgb(224, 62, 45);"> conn.send(f"ERROR: Block failed - {str(e)}".encode())</span>  
<span style="color: rgb(224, 62, 45);"> else:</span>  
<span style="color: rgb(224, 62, 45);"> conn.send(b"ERROR: Invalid IP format for block")</span>  
<span style="color: rgb(224, 62, 45);"> </span>  
<span style="color: rgb(224, 62, 45);"> except Exception as e:</span>  
<span style="color: rgb(224, 62, 45);"> conn.send(f"ERROR: Server error - {str(e)}".encode())</span>  
<span style="color: rgb(224, 62, 45);"> finally:</span>  
<span style="color: rgb(224, 62, 45);"> conn.close()</span>

**nano /usr/local/bin/block-ip.sh**  
isi:  
<span style="color: rgb(224, 62, 45);">\#!/bin/bash</span>  
<span style="color: rgb(224, 62, 45);">IP=$1</span>  
<span style="color: rgb(224, 62, 45);">iptables -A INPUT -s $IP -j DROP</span>

**nano /usr/local/bin/unblock-ip.sh**  
isi:  
<span style="color: rgb(224, 62, 45);">\#!/bin/bash</span>  
<span style="color: rgb(224, 62, 45);">IP=$1</span>  
<span style="color: rgb(224, 62, 45);">iptables -D INPUT -s $IP -j DROP</span>

6\. Berikan akses www-data untuk menjalankan shell block-ip.sh dan unblock-ip.sh  
**nano /etc/sudoers**  
isi:  
<span style="color: rgb(224, 62, 45);">\#</span>

<span style="color: rgb(224, 62, 45);">\# This file MUST be edited with the 'visudo' command as root.</span>  
<span style="color: rgb(224, 62, 45);">\#</span>  
<span style="color: rgb(224, 62, 45);">\# Please consider adding local content in /etc/sudoers.d/ instead of</span>  
<span style="color: rgb(224, 62, 45);">\# directly modifying this file.</span>  
<span style="color: rgb(224, 62, 45);">\#</span>  
<span style="color: rgb(224, 62, 45);">\# See the man page for details on how to write a sudoers file.</span>  
<span style="color: rgb(224, 62, 45);">\#</span>  
<span style="color: rgb(224, 62, 45);">Defaults env\_reset</span>  
<span style="color: rgb(224, 62, 45);">Defaults mail\_badpass</span>  
<span style="color: rgb(224, 62, 45);">Defaults secure\_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"</span>

<span style="color: rgb(224, 62, 45);">\# Host alias specification</span>

<span style="color: rgb(224, 62, 45);">\# User alias specification</span>

<span style="color: rgb(224, 62, 45);">\# Cmnd alias specification</span>

<span style="color: rgb(224, 62, 45);">\# User privilege specification</span>  
<span style="color: rgb(224, 62, 45);">root ALL=(ALL:ALL) ALL</span>

<span style="color: rgb(224, 62, 45);">\# Members of the admin group may gain root privileges</span>  
<span style="color: rgb(224, 62, 45);">%admin ALL=(ALL) ALL</span>

<span style="color: rgb(224, 62, 45);">\# Allow members of group sudo to execute any command</span>  
<span style="color: rgb(224, 62, 45);">%sudo ALL=(ALL:ALL) ALL</span>

<span style="color: rgb(224, 62, 45);">\# See sudoers(5) for more information on "#include" directives:</span>

<span style="color: rgb(224, 62, 45);">\#includedir /etc/sudoers.d</span>

<span style="color: rgb(224, 62, 45);">**\#fungsi tambahan blokir lewa app logwebmin**</span>  
<span style="color: rgb(224, 62, 45);">www-data ALL=(ALL) NOPASSWD: /usr/local/bin/block-ip.sh</span>  
<span style="color: rgb(224, 62, 45);">www-data ALL=(ALL) NOPASSWD: /usr/local/bin/unblock-ip.sh</span>

7\. Jalankan service daemon  
**sudo systemctl daemon-reload**  
**sudo systemctl restart ipblock.socket ipblock.service**  
**sudo systemctl enable ipblock.socket**

8\. Verifikasi service  
**sudo systemctl status ipblock.service**  
**journalctl -u ipblock.service -f**

9\. Pastikan anda telah mendaftar akun pada [https://www.maxmind.com/](https://www.maxmind.com/)  
untuk mendapatkan license-key seperti pada contoh berikut:

[![image.png](https://dokumen.baritotimurkab.go.id/uploads/images/gallery/2025-05/scaled-1680-/O0KaS8oNtVVvEDcA-image.png)](https://dokumen.baritotimurkab.go.id/uploads/images/gallery/2025-05/O0KaS8oNtVVvEDcA-image.png)

agar dapat diinisiasikan pada .env

[![image.png](https://dokumen.baritotimurkab.go.id/uploads/images/gallery/2025-05/scaled-1680-/y4jcCgQRkdV15syq-image.png)](https://dokumen.baritotimurkab.go.id/uploads/images/gallery/2025-05/y4jcCgQRkdV15syq-image.png)

# Monitoring Koneksi Aktif ke Server

Untuk melihat koneksi aktif ke server Anda, termasuk IP yang terhubung, gunakan `netstat`:  
secara real time setiap 2 detik:

`watch -n 2 netstat -ntu`

contoh hasil:

`Every 2.0s: netstat -ntu                                                 kominfos-0B: Tue Jun 24 21:28:23 2025` `Active Internet connections (w/o servers)Proto Recv-Q Send-Q Local Address           Foreign Address         Statetcp        0      0 127.0.0.1:3306          127.0.0.1:47308         ESTABLISHEDtcp        0      0 127.0.0.1:57164         127.0.0.1:556           ESTABLISHEDtcp        0      0 127.0.0.1:38366         127.0.0.1:3306          ESTABLISHEDtcp        0      0 127.0.0.1:556           127.0.0.1:57164         ESTABLISHEDtcp        0      0 192.168.80.51:22        196.251.70.166:57154    ESTABLISHEDtcp        0      0 192.168.80.51:41344     91.189.91.48:80         TIME_WAITtcp        0      0 192.168.80.51:2014      222.124.78.211:59143    ESTABLISHEDtcp        0      0 127.0.0.1:47308         127.0.0.1:3306          ESTABLISHEDtcp        0      0 127.0.0.1:3306          127.0.0.1:38366         ESTABLISHEDtcp        0      0 192.168.80.51:22        222.124.78.211:59160    ESTABLISHEDtcp6       0      0 192.168.80.51:443       114.125.120.16:41242    TIME_WAITtcp6       0      0 192.168.80.51:80        45.82.76.192:41150      SYN_RECVtcp6       0     25 192.168.80.51:443       177.93.63.18:45129      CLOSINGudp        0      0 192.168.80.51:68        192.168.80.1:67         ESTABLISHEDudp        0      0 169.254.95.120:68       169.254.95.118:67       ESTABLISHED`

#### **Daftar Status Koneksi TCP &amp; Penjelasannya**

<div class="_tableContainer_16hzy_1" id="bkmrk-state-penjelasan-est"><div class="_tableWrapper_16hzy_14 group flex w-fit flex-col-reverse" tabindex="-1"><table class="w-fit min-w-(--thread-content-width)" data-end="1778" data-start="219" style="width: 100%;"><thead data-end="257" data-start="219"><tr data-end="257" data-start="219"><th data-col-size="sm" data-end="239" data-start="219" style="width: 13.4659%;">**State**</th><th data-col-size="xl" data-end="257" data-start="239" style="width: 86.6329%;">**Penjelasan**</th></tr></thead><tbody data-end="1778" data-start="297"><tr data-end="459" data-start="297"><td data-col-size="sm" data-end="317" data-start="297" style="width: 13.4659%;">**ESTABLISHED**</td><td data-col-size="xl" data-end="459" data-start="317" style="width: 86.6329%;">Koneksi telah terbentuk dan aktif digunakan untuk komunikasi data. Ini adalah koneksi yang “normal” dan siap untuk transfer data dua arah.</td></tr><tr data-end="617" data-start="460"><td data-col-size="sm" data-end="480" data-start="460" style="width: 13.4659%;">**SYN\_SENT**</td><td data-col-size="xl" data-end="617" data-start="480" style="width: 86.6329%;">Klien telah mengirim paket SYN ke server dan sedang menunggu balasan (SYN-ACK). Ini adalah tahap awal dari koneksi outbound (keluar).</td></tr><tr data-end="777" data-start="618"><td data-col-size="sm" data-end="638" data-start="618" style="width: 13.4659%;">**SYN\_RECV**</td><td data-col-size="xl" data-end="777" data-start="638" style="width: 86.6329%;">Server telah menerima SYN dari klien, membalas dengan SYN-ACK, dan sedang menunggu ACK dari klien untuk menyelesaikan proses handshake.</td></tr><tr data-end="905" data-start="778"><td data-col-size="sm" data-end="798" data-start="778" style="width: 13.4659%;">**FIN\_WAIT1**</td><td data-col-size="xl" data-end="905" data-start="798" style="width: 86.6329%;">Aplikasi telah menutup koneksi, dan sistem telah mengirim FIN (permintaan tutup koneksi) ke pihak lain.</td></tr><tr data-end="1006" data-start="906"><td data-col-size="sm" data-end="926" data-start="906" style="width: 13.4659%;">**FIN\_WAIT2**</td><td data-col-size="xl" data-end="1006" data-start="926" style="width: 86.6329%;">Setelah menerima ACK dari FIN pertama, sistem menunggu FIN dari pihak lawan.</td></tr><tr data-end="1215" data-start="1007"><td data-col-size="sm" data-end="1027" data-start="1007" style="width: 13.4659%;">**TIME\_WAIT**</td><td data-col-size="xl" data-end="1215" data-start="1027" style="width: 86.6329%;">Koneksi ditutup, tapi sistem menunggu selama periode waktu tertentu (biasanya 2x waktu maksimum segment life) untuk memastikan semua paket terlambat tidak akan menyebabkan kebingungan.</td></tr><tr data-end="1324" data-start="1216"><td data-col-size="sm" data-end="1236" data-start="1216" style="width: 13.4659%;">**CLOSE\_WAIT**</td><td data-col-size="xl" data-end="1324" data-start="1236" style="width: 86.6329%;">Server menerima FIN dari klien, dan menunggu aplikasinya untuk menutup koneksi juga.</td></tr><tr data-end="1410" data-start="1325"><td data-col-size="sm" data-end="1345" data-start="1325" style="width: 13.4659%;">**CLOSING**</td><td data-col-size="xl" data-end="1410" data-start="1345" style="width: 86.6329%;">Kedua sisi telah mengirim FIN, tapi belum semua ACK diterima.</td></tr><tr data-end="1536" data-start="1411"><td data-col-size="sm" data-end="1431" data-start="1411" style="width: 13.4659%;">**LAST\_ACK**</td><td data-col-size="xl" data-end="1536" data-start="1431" style="width: 86.6329%;">Sistem telah mengirim FIN (balasan), menunggu ACK dari pihak lain sebelum sepenuhnya menutup koneksi.</td></tr><tr data-end="1629" data-start="1537"><td data-col-size="sm" data-end="1557" data-start="1537" style="width: 13.4659%;">**CLOSED**</td><td data-col-size="xl" data-end="1629" data-start="1557" style="width: 86.6329%;">Koneksi telah ditutup sepenuhnya, tidak ada komunikasi lebih lanjut.</td></tr><tr data-end="1778" data-start="1630"><td data-col-size="sm" data-end="1650" data-start="1630" style="width: 13.4659%;">**LISTEN**</td><td data-col-size="xl" data-end="1778" data-start="1650" style="width: 86.6329%;">Server menunggu koneksi masuk pada port tertentu (passive open). Biasanya terlihat pada server seperti web server, SSH, dll.</td></tr></tbody></table>

<div class="sticky end-(--thread-content-margin) h-0 self-end select-none"><div class="absolute end-0 flex items-end">  
</div></div></div></div>---

#### **Contoh Alur Normal TCP (3-way handshake + closing)**

**Pembukaan koneksi:**

1. Klien: `SYN_SENT`
2. Server: `SYN_RECV`
3. Keduanya: `ESTABLISHED`

**Penutupan koneksi:**

1. Pengirim: `FIN_WAIT1`
2. Penerima: `CLOSE_WAIT`
3. Pengirim: `FIN_WAIT2`
4. Penerima: `LAST_ACK`
5. Keduanya: `TIME_WAIT`
6. Akhir: `CLOSED`

---

#### **Status yang Perlu Diwaspadai**

- **SYN\_RECV** banyak → kemungkinan *SYN flood attack*
- **TIME\_WAIT** banyak → bisa akibat skrip web atau API client yang membuka-tutup koneksi terus-menerus
- **CLOSE\_WAIT** menggantung → aplikasi Anda tidak menutup koneksi dengan benar (potensi memory leak)

# Cek Lokasi File Exploit pada Root Web

Cek Lokasi file Exploit yang menggunakan **shell\_exec**, **curl\_exec** dan simpan hasilnya di hasil\_scan.txt

`cd /var/www/html/root_aplikasi`

`grep -RniE 'eval\s*\(|base64_decode\s*\(|assert\s*\(|shell_exec\s*\(|system\s*\(|passthru\s*\(|file_get_contents\s*\(' . > hasil_scan.txt`

`grep -RniE 'eval\s*\(|base64_decode\s*\(|assert\s*\(|curl_exec\s*\(|system\s*\(|passthru\s*\(|file_get_contents\s*\(' . > hasil_scan2.txt`

lihat hasilnya lalu hapus file tersebut (paling mencurigakan file .php yang berada di public atau storage)

# Mengamankan PHP

## <span class="mw-headline" id="bkmrk-mengamankan-php-apac-1">Mengamankan PHP Apache</span>

Untuk membatasi serangan hacker pada PHP dalam instalasi LAMPP (Linux, Apache, MySQL, PHP, PHPMyAdmin), Anda dapat mengambil beberapa langkah keamanan untuk melindungi aplikasi web Anda dari berbagai jenis serangan. Berikut adalah beberapa konfigurasi dan praktik keamanan umum yang dapat membantu Anda:

**Update PHP** Pastikan Anda menjalankan versi PHP yang paling baru dan selalu diperbarui. Setiap pembaruan PHP biasanya mencakup perbaikan keamanan. Anda juga dapat mempertimbangkan untuk menggunakan PHP versi 8.x atau yang lebih baru, karena ini mendukung peningkatan keamanan dan kinerja.

**Konfigurasi PHP**  
Edit file **php.ini** di **/etc/php/8.1/cli/php.ini** dan/atau **/etc/php/8.1/apache2/php.ini** dan terapkan konfigurasi keamanan berikut:

- Batasi maksimum ukuran upload file dengan parameter **`upload_max_filesize`** dan **`post_max_size`**.
- Matikan **`register_globals`**.
- Matikan **`allow_url_fopen`** dan **`allow_url_include`** untuk mencegah inklusi dan akses ke URL eksternal.
- Setel **`display_errors`** menjadi **Off** dalam produksi untuk menghindari menampilkan kesalahan PHP ke publik.
- Aktifkan disable\_functions untuk memblokir fungsi-fungsi berbahaya jika Anda tahu apa yang Anda lakukan.
- Aktifkan open\_basedir untuk membatasi direktori yang diizinkan PHP untuk mengakses.

Menggunakan opsi **`disable_functions`** dalam konfigurasi PHP dapat membantu mengurangi risiko keamanan dengan memblokir fungsi-fungsi tertentu yang dapat digunakan oleh penyerang untuk melakukan aktivitas berbahaya. Namun, penggunaan **`disable_functions`** harus dilakukan dengan hati-hati, karena mematikan fungsi-fungsi tertentu dapat mempengaruhi fungsi normal dari aplikasi PHP Anda. Beberapa fungsi yang sering kali dinonaktifkan karena potensi risiko keamanan termasuk:

1. **exec**: Fungsi `exec()` digunakan untuk menjalankan perintah shell dari dalam skrip PHP. Ini harus dinonaktifkan untuk mencegah penyerang menjalankan perintah shell di server Anda.
2. **system**: Sama seperti `exec()`, `system()` juga digunakan untuk menjalankan perintah shell. Ini harus dinonaktifkan.
3. **shell\_exec**: Fungsi `shell_exec()` juga digunakan untuk menjalankan perintah shell dan harus dinonaktifkan.
4. **passthru**: `passthru()` adalah fungsi lain yang dapat digunakan untuk menjalankan perintah shell. Ini juga harus dinonaktifkan.
5. **popen**: `popen()` memungkinkan skrip PHP untuk membuka pipe ke proses eksternal. Ini harus dinonaktifkan.
6. **proc\_open**: Fungsi ini serupa dengan `popen()` dan juga digunakan untuk menjalankan proses eksternal. Ini harus dinonaktifkan.
7. **eval**: Fungsi `eval()` digunakan untuk mengeksekusi kode PHP dari string. Penyerang dapat memanfaatkannya dengan memasukkan kode berbahaya ke dalam string.
8. **assert:** Fungsi `assert()` juga dapat digunakan untuk mengeksekusi kode PHP dari string. Ini harus dinonaktifkan.
9. **system\_popen**: Ini adalah alternatif lain untuk `popen()` dan harus dinonaktifkan.
10. **dl**: Fungsi `dl()` digunakan untuk memuat ekstensi PHP dinamis. Ini dapat membuka celah keamanan jika dinonaktifkan.
11. **proc\_close:** Ini adalah fungsi terkait dengan `proc_open()` yang digunakan untuk menutup proses yang telah dibuka dengan `proc_open()`. Dinonaktifkan juga.
12. **pcntl\_exec**: Fungsi ini memungkinkan penggunaan fungsi `exec()` dalam lingkungan PHP-FPM. Jika Anda tidak menggunakannya, disarankan untuk dinonaktifkan.

  
Cari baris yang mengandung **`disable_functions`**. Jika Anda tidak menemukannya, Anda dapat menambahkannya di bagian paling bawah file **php.ini**.

Tambahkan nama fungsi-fungsi yang ingin Anda nonaktifkan, dipisahkan oleh tanda koma. Misalnya, jika Anda ingin menonaktifkan fungsi exec, system, dan eval, tambahkan baris berikut:

**`disable_functions = exec, system, eval`**

Setelah menyimpan perubahan, Anda perlu merestart Apache agar perubahan ini berlaku:

**systemctl restart apache2**

**Catatan:  
Pastikan bahwa Anda memeriksa bahwa aplikasi PHP Anda tetap berfungsi dengan baik setelah mengaktifkan disable\_functions**, karena beberapa fungsi PHP mungkin diperlukan untuk fungsi normal aplikasi Anda. Selalu uji aplikasi Anda dengan cermat setelah mengubah pengaturan ini.