summaryrefslogtreecommitdiff
path: root/guides/cloud/vps.org
blob: 1224a177faaa86eddf6d6bdc702b3acb5af954de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
* Security
** Switch APT to HTTPS
~sudo sed -i 's/http:/https:/' /etc/apt/sources.list~

Granted, the repository signature provides enough protection; still,
no sense in wasting bandwidth and CPU if someone is meddling.
** Tweak root access
On OVH's Debian image:
- The =root= account has no password.
- =PermitRootLogin= defaults to =prohibit-password=: set it to =no=.
** Enable fail2ban
~lastb~ says there's about 4000 login attempts per day; that makes
=/var/log/btmp= much bigger than it needs to be.

Debian's fail2ban comes with a jail for ~sshd~, so it's just a matter
of ~apt install fail2ban~.
** Tweak user accounts
=debian= seems mildly popular among bots looking for valid usernames.

Ideally I'd just rename the =debian= account, but renaming does not
seem to be a very well-defined operation: ~usermod --login $name
--move-home --home /home/$name debian~ gets partway there, but leaves
a bunch of miscellany to take care of (e.g. sudoers).

So instead, I'll
- create my own user account: ~sudo adduser $name~
- add it to all groups =debian= belongs to:
  #+begin_src sh
  groups=$(groups | sed -e 's/ *debian *//' -e 's/ /,/g')
  sudo usermod --append --groups ${groups} ${name}
  #+end_src
- only allow password authentication over SSH for this new user
  account:
  #+begin_src conf
  PasswordAuthentication no
  Match User …
  	PasswordAuthentication yes
  #+end_src

* System
** Hostname
#+begin_src sh
sudo hostnamectl set-hostname $fqdn
#+end_src

* Services
** Web server
Run ~sudo apt install nginx~; then, in
=/etc/nginx/sites-available/$FQDN=:
#+begin_src conf
server {
	listen 80;
	listen [::]:80;

	root /var/www/$FQDN/html;
	index index.html;

	server_name $FQDN www.$FQDN;
	access_log /var/log/nginx/$FQDN.access.log;

	location / {
		try_files $uri $uri/ =404;
	}
}
#+end_src
Use one =access_log= file per site, to simplify analytics.

Run ~sudo systemctl restart nginx~.
*** fail2ban
With the following files in =$HOME=:
#+begin_src conf
# nginx-botsearch.local
[Init]

block = \S*(php|wp-|wordpress|jenkins|hudson|sql|boaform)[^,]*

[Definition]

# Change from distro: just remove the leading slash before <block>.
failregex = ^<HOST> \- \S+ \[\] \"(GET|POST|HEAD) <block> \S+\" 404 .+$
            ^ \[error\] \d+#\d+: \*\d+ (\S+ )?\"\S+\" (failed|is not found) \(2\: No such file or directory\), client\: <HOST>\, server\: \S*\, request: \"(GET|POST|HEAD) \/<block> \S+\"\, .*?$

# jail.local
[nginx-http-auth]
enabled = true

[nginx-botsearch]
enabled = true
# Assume that each requests to $fqdn will be logged to "$fqdn.access.log".
logpath = /var/log/nginx/*access.log
#+end_src

Then:
#+begin_src sh
sudo cp ~/nginx-botsearch.local /etc/fail2ban/filter.d/
sudo cp ~/jail.local /etc/fail2ban/
sudo systemctl restart fail2ban
#+end_src

Check how these rules fare against real bot searches with
~fail2ban-regex /var/log/nginx/access.log
/etc/fail2ban/filter.d/nginx-botsearch.local~.
** Git server
*** SSH access
#+begin_src sh
$ sudo apt install git
$ sudo tee -a /etc/shells <<< $(which git-shell)
$ sudo adduser git --disabled-password --shell $(which git-shell)
$ sudo mkdir /srv/git
$ sudo chown git:git /srv/git
# For every new repo:
$ sudo -u git git init --bare --shared=group /srv/git/${repo}
#+end_src

*** TODO Web mirror