add timestamp to auth log, add fail2ban conf+docs

This commit is contained in:
Dean Sheather 2019-07-09 10:57:09 +10:00
parent 14d917179c
commit c48a275d33
No known key found for this signature in database
GPG Key ID: B574DF7CAFDCFAA3
3 changed files with 60 additions and 1 deletions
doc/security
packages/server/src

View File

@ -0,0 +1,15 @@
# Fail2Ban filter for code-server
#
#
[Definition]
failregex = ^INFO\s+Failed login attempt\s+{\"password\":\"(\\.|[^"])*\",\"remote_address\":\"<HOST>\"
ignoreregex =
datepattern = "timestamp":{EPOCH}}$
# Author: Dean Sheather

42
doc/security/fail2ban.md Normal file
View File

@ -0,0 +1,42 @@
# Protecting code-server from bruteforce attempts
code-server outputs all failed login attempts, along with the IP address,
provided password, user agent and timestamp by default. When using a reverse
proxy such as Nginx or Apache, the remote address may appear to be `127.0.0.1`
or a similar address unless the `--trust-proxy` argument is provided to
code-server.
When used with the `--trust-proxy` argument, code-server will use the last IP in
`X-Forwarded-For` (if provided) instead of the remote socket address. Ensure
that you are setting this value in your reverse proxy:
Nginx:
```
location / {
...
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
...
}
```
Apache:
```
<VirtualEnv>
...
SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
...
</VirtualEnv>
```
It is extremely important that if you enable `--trust-proxy` you ensure your
code-server instance is not accessible from the internet (block it in your
firewall).
## Fail2Ban
Fail2Ban allows for automatically banning and logging repeated failed
authentication attempts for many applications through regex filters. A working
filter for code-server can be found in `./code-server.fail2ban.conf`. Once this
is installed and configured correctly, repeated failed login attempts should
automatically be banned from connecting to your server.

View File

@ -89,13 +89,15 @@ export const createApp = async (options: CreateAppOptions): Promise<{
if (cookies.password) {
if (!safeCompare(cookies.password, options.password)) {
let userAgent = req.headers["user-agent"];
let timestamp = Math.floor(new Date().getTime() / 1000);
if (Array.isArray(userAgent)) {
userAgent = userAgent.join(", ");
}
logger.info("Failed login attempt",
field("password", cookies.password),
field("remote_address", remoteAddress(req)),
field("user_agent", userAgent));
field("user_agent", userAgent),
field("timestamp", timestamp));
return false;
}