diff --git a/doc/security/code-server.fail2ban.conf b/doc/security/code-server.fail2ban.conf new file mode 100644 index 000000000..3f4edae42 --- /dev/null +++ b/doc/security/code-server.fail2ban.conf @@ -0,0 +1,15 @@ +# Fail2Ban filter for code-server +# +# + +[Definition] + + +failregex = ^INFO\s+Failed login attempt\s+{\"password\":\"(\\.|[^"])*\",\"remote_address\":\"\" + +ignoreregex = + +datepattern = "timestamp":{EPOCH}}$ + +# Author: Dean Sheather + diff --git a/doc/security/fail2ban.md b/doc/security/fail2ban.md new file mode 100644 index 000000000..a9ad86810 --- /dev/null +++ b/doc/security/fail2ban.md @@ -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: +``` + + ... + SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded + ... + +``` + +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. + diff --git a/packages/server/src/server.ts b/packages/server/src/server.ts index 4c73743ad..70dbb7654 100644 --- a/packages/server/src/server.ts +++ b/packages/server/src/server.ts @@ -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; }