Skip to content

Commit df37bb3

Browse files
committed
Added: vps secure setup
1 parent fff5a4f commit df37bb3

File tree

3 files changed

+260
-85
lines changed

3 files changed

+260
-85
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Fail2Ban Alerts to Discord
2+
3+
A simple guide to setup fail2ban action for sending an alert message to discord channel.
4+
5+
1. Create a Discord Webhook
6+
- Go to your Discord Server → Select a channel.
7+
- Click Edit Channel → Integrations → Webhooks → New Webhook.
8+
- Name it (ex: Fail2Ban Alerts) and copy the Webhook URL.
9+
- Example: `https://discord.com/api/webhooks/1234567890/abcdefghijklmnopqrstuvwxyz`
10+
11+
2. Create the Discord Notification Script
12+
- install `jq`:
13+
14+
```bash
15+
sudo apt install jq
16+
```
17+
18+
- Create the file `/usr/local/bin/fail2ban-discord.sh`:
19+
20+
```bash
21+
#!/bin/bash
22+
23+
JAIL="$1"
24+
IP="$2"
25+
MATCHES="$3"
26+
27+
WEBHOOK_URL="YOUR-WEBHOOK-URL"
28+
29+
HOSTNAME=$(hostname)
30+
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
31+
32+
MESSAGE="** Fail2Ban Alert**
33+
**Server:** ${HOSTNAME}
34+
**Time:** ${TIMESTAMP}
35+
**Jail:** \`${JAIL}\`
36+
**Banned IP:** \`${IP}\`
37+
**Reason:** ${MATCHES}"
38+
39+
# Send to Discord
40+
curl -s -H "Content-Type: application/json" \
41+
-X POST \
42+
-d "$(jq -nc --arg content "$MESSAGE" '{content: $content}')" \
43+
"$WEBHOOK_URL"
44+
```
45+
46+
- Make it executable:
47+
48+
```bash
49+
sudo chmod +x /usr/local/bin/fail2ban-discord.sh
50+
```
51+
52+
3. Create a Custom Fail2Ban Action
53+
54+
- Create `/etc/fail2ban/action.d/discord-ban.conf`:
55+
56+
```ini
57+
[Definition]
58+
actionstart =
59+
actionstop =
60+
actioncheck =
61+
actionban = /usr/local/bin/fail2ban-discord.sh "<name>" "<ip>" "<matches>"
62+
actionunban =
63+
```
64+
65+
4. Apply It in Jail Config
66+
- Edit /etc/fail2ban/jail.local or create if not existing:
67+
68+
```ini
69+
[sshd]
70+
enabled = true
71+
port = ssh
72+
logpath = /var/log/auth.log
73+
maxretry = 3
74+
findtime = 600
75+
bantime = 3600
76+
action = discord-ban
77+
```
78+
79+
5. Restart fail2ban
80+
81+
```bash
82+
sudo systemctl restart fail2ban
83+
```
84+
85+
6. Test
86+
87+
To test, you can intentionally trigger a failed login from a different IP or use:
88+
89+
```bash
90+
sudo fail2ban-client set sshd banip 192.168.0.1
91+
```
92+
93+
All are done!. You should receive an alert in your Discord channel like below.
94+
95+
```text
96+
Fail2Ban Alert
97+
Server: srv627828
98+
Time: 2025-05-29 00:06:40
99+
Jail: sshd
100+
Banned IP: 191.7.190.74
101+
Reason: May 28 23:53:53 srv627828 sshd[52304]: Invalid user katarina from 191.7.190.74 port 44770
102+
May 28 23:53:53 srv627828 sshd[52304]: Failed password for invalid user katarina from 191.7.190.74 port 44770 ssh2
103+
May 29 00:06:39 srv627828 sshd[52915]: Failed password for postfix from 191.7.190.74 port 30736 ssh2
104+
```

projects/secure-vps/README.md

Lines changed: 26 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,32 @@
1-
# Fail2Ban Alerts to Discord
2-
A simple guide to setup fail2ban action for sending an alert message to discord channel.
1+
# Secure VPS From Bruteforce SSH Attack
32

4-
1. Create a Discord Webhook
5-
- Go to your Discord Server → Select a channel.
6-
- Click Edit Channel → Integrations → Webhooks → New Webhook.
7-
- Name it (ex: Fail2Ban Alerts) and copy the Webhook URL.
8-
- Example: `https://discord.com/api/webhooks/1234567890/abcdefghijklmnopqrstuvwxyz`
3+
## Secure SSH connection
94

10-
2. Create the Discord Notification Script
11-
- install `jq`:
12-
```bash
13-
sudo apt install jq
14-
```
15-
- Create the file `/usr/local/bin/fail2ban-discord.sh`:
16-
```bash
17-
#!/bin/bash
18-
19-
JAIL="$1"
20-
IP="$2"
21-
MATCHES="$3"
22-
23-
WEBHOOK_URL="YOUR-WEBHOOK-URL"
24-
25-
HOSTNAME=$(hostname)
26-
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
27-
28-
MESSAGE="** Fail2Ban Alert**
29-
**Server:** ${HOSTNAME}
30-
**Time:** ${TIMESTAMP}
31-
**Jail:** \`${JAIL}\`
32-
**Banned IP:** \`${IP}\`
33-
**Reason:** ${MATCHES}"
34-
35-
# Send to Discord
36-
curl -s -H "Content-Type: application/json" \
37-
-X POST \
38-
-d "$(jq -nc --arg content "$MESSAGE" '{content: $content}')" \
39-
"$WEBHOOK_URL"
40-
```
41-
- Make it executable:
42-
```bash
43-
sudo chmod +x /usr/local/bin/fail2ban-discord.sh
44-
```
45-
3. Create a Custom Fail2Ban Action
46-
- Create `/etc/fail2ban/action.d/discord-ban.conf`:
47-
```ini
48-
[Definition]
49-
actionstart =
50-
actionstop =
51-
actioncheck =
52-
actionban = /usr/local/bin/fail2ban-discord.sh "<name>" "<ip>" "<matches>"
53-
actionunban =
54-
```
55-
56-
4. Apply It in Jail Config
57-
- Edit /etc/fail2ban/jail.local or create if not existing:
58-
```ini
59-
[sshd]
60-
enabled = true
61-
port = ssh
62-
logpath = /var/log/auth.log
63-
maxretry = 3
64-
findtime = 600
65-
bantime = 3600
66-
action = discord-ban
67-
```
68-
5. Restart fail2ban
69-
```bash
70-
sudo systemctl restart fail2ban
71-
```
5+
1. Disbaled password based authentication and Make sure PublicKey based Authentication is enabled:
726

73-
6. Test
7+
```ini
8+
PasswordAuthentication no
9+
PubkeyAuthentication yes
10+
```
7411

75-
To test, you can intentionally trigger a failed login from a different IP or use:
76-
```bash
77-
sudo fail2ban-client set sshd banip 192.168.0.1
78-
```
12+
2. Better to keep root login disabled:
7913

80-
All are done!. You should receive an alert in your Discord channel like below.
14+
```ini
15+
PermitRootLogin no
16+
```
8117

82-
```text
83-
Fail2Ban Alert
84-
Server: srv627828
85-
Time: 2025-05-29 00:06:40
86-
Jail: sshd
87-
Banned IP: 191.7.190.74
88-
Reason: May 28 23:53:53 srv627828 sshd[52304]: Invalid user katarina from 191.7.190.74 port 44770
89-
May 28 23:53:53 srv627828 sshd[52304]: Failed password for invalid user katarina from 191.7.190.74 port 44770 ssh2
90-
May 29 00:06:39 srv627828 sshd[52915]: Failed password for postfix from 191.7.190.74 port 30736 ssh2
91-
```
18+
Alternatively, you can allow ssh-key based authentication for root user:
19+
20+
```ini
21+
PermitRootLogin prohibit-password
22+
```
23+
24+
3. If it's still asking password when key doesn't match then forecuflly disabled by setting:
25+
26+
```ini
27+
AuthenticationMethods publickey
28+
```
29+
30+
4. Finally, If possible change the default port `22` to something else. It's hard to guess someone which port ssh using in this case. Checkout [sshd_config](./setup-sshd-config.md)
31+
32+
5. (Optional): Use third party tool `fail2ban` to monitor and ban IP from suspect attack. See [How to Setup Fail2ban and connect with Discord](./Fail2ban-to-discord-alerts.md) to block IP and sending alert as action.
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Secure SSH Connection
2+
3+
```ini
4+
#AllowUsers fpt gitlab
5+
6+
# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $
7+
8+
# This is the sshd server system-wide configuration file. See
9+
# sshd_config(5) for more information.
10+
11+
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
12+
13+
# The strategy used for options in the default sshd_config shipped with
14+
# OpenSSH is to specify options with their default value where
15+
# possible, but leave them commented. Uncommented options override the
16+
# default value.
17+
18+
Include /etc/ssh/sshd_config.d/*.conf
19+
20+
Port 22
21+
#AddressFamily any
22+
#ListenAddress 0.0.0.0
23+
#ListenAddress ::
24+
25+
#HostKey /etc/ssh/ssh_host_rsa_key
26+
#HostKey /etc/ssh/ssh_host_ecdsa_key
27+
#HostKey /etc/ssh/ssh_host_ed25519_key
28+
29+
# Ciphers and keying
30+
#RekeyLimit default none
31+
32+
# Logging
33+
#SyslogFacility AUTH
34+
#LogLevel INFO
35+
36+
# Authentication:
37+
38+
#LoginGraceTime 2m
39+
#StrictModes yes
40+
#MaxAuthTries 6
41+
#MaxSessions 10
42+
43+
PubkeyAuthentication yes
44+
45+
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
46+
AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
47+
48+
#AuthorizedPrincipalsFile none
49+
50+
#AuthorizedKeysCommand none
51+
#AuthorizedKeysCommandUser nobody
52+
53+
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
54+
#HostbasedAuthentication no
55+
# Change to yes if you don't trust ~/.ssh/known_hosts for
56+
# HostbasedAuthentication
57+
#IgnoreUserKnownHosts no
58+
# Don't read the user's ~/.rhosts and ~/.shosts files
59+
#IgnoreRhosts yes
60+
61+
# To disable tunneled clear text passwords, change to no here!
62+
PasswordAuthentication no
63+
#PermitEmptyPasswords no
64+
65+
# Change to yes to enable challenge-response passwords (beware issues with
66+
# some PAM modules and threads)
67+
ChallengeResponseAuthentication no
68+
69+
# Kerberos options
70+
#KerberosAuthentication no
71+
#KerberosOrLocalPasswd yes
72+
#KerberosTicketCleanup yes
73+
#KerberosGetAFSToken no
74+
75+
# GSSAPI options
76+
#GSSAPIAuthentication no
77+
#GSSAPICleanupCredentials yes
78+
#GSSAPIStrictAcceptorCheck yes
79+
#GSSAPIKeyExchange no
80+
81+
# Set this to 'yes' to enable PAM authentication, account processing,
82+
# and session processing. If this is enabled, PAM authentication will
83+
# be allowed through the ChallengeResponseAuthentication and
84+
# PasswordAuthentication. Depending on your PAM configuration,
85+
# PAM authentication via ChallengeResponseAuthentication may bypass
86+
# If you just want the PAM account and session checks to run without
87+
# PAM authentication, then enable this but set PasswordAuthentication
88+
# and ChallengeResponseAuthentication to 'no'.
89+
UsePAM yes
90+
91+
#AllowAgentForwarding yes
92+
#AllowTcpForwarding yes
93+
#GatewayPorts no
94+
X11Forwarding yes
95+
#X11DisplayOffset 10
96+
#X11UseLocalhost yes
97+
#PermitTTY yes
98+
PrintMotd no
99+
#PrintLastLog yes
100+
#TCPKeepAlive yes
101+
#PermitUserEnvironment no
102+
#Compression delayed
103+
#ClientAliveInterval 0
104+
#ClientAliveCountMax 3
105+
#UseDNS no
106+
#PidFile /var/run/sshd.pid
107+
#MaxStartups 10:30:100
108+
#PermitTunnel no
109+
#ChrootDirectory none
110+
#VersionAddendum none
111+
112+
# no default banner path
113+
#Banner none
114+
115+
# Allow client to pass locale environment variables
116+
AcceptEnv LANG LC_*
117+
118+
# override default of no subsystems
119+
Subsystem sftp /usr/lib/openssh/sftp-server
120+
121+
# Example of overriding settings on a per-user basis
122+
#Match User anoncvs
123+
#X11Forwarding no
124+
#AllowTcpForwarding no
125+
#PermitTTY no
126+
#ForceCommand cvs server
127+
PermitRootLogin no
128+
# yes prohibit-password
129+
AuthenticationMethods publickey
130+
```

0 commit comments

Comments
 (0)