admin/home: proxy warning will last only for one day after last triggering request
Massimo Melina committed
Apr 9, 2023 at 20:27 UTC
e9df9472d8cb04c5a1be92831988621e4c87db00
3 files changed
+20
-15
admin/src/HomePage.ts
+2
-2
@@ -22,7 +22,7 @@ export default function HomePage() {
22
const { data: status, reload: reloadStatus, element: statusEl } = useApiEx<Dict<ServerStatus>>('get_status')
23
const { data: vfs } = useApiEx<{ root?: VfsNode }>('get_vfs')
24
const [account] = useApi<Account>(username && 'get_account')
25
- const { data: cfg, reload: reloadCfg } = useApiEx('get_config', { only: ['https_port', 'cert', 'private_key', 'proxies', 'ignore_proxies'] })
25
+ const { data: cfg, reload: reloadCfg } = useApiEx('get_config', { only: ['https_port', 'cert', 'private_key', 'proxies'] })
26
const { list: plugins } = useApiList('get_plugins')
27
if (statusEl || !status)
28
return statusEl
@@ -98,5 +98,5 @@ function cfgLink(text=`Options page`) {
98
}
99
100
export function proxyWarning(cfg: any, status: any) {
101
- return cfg && !cfg.proxies && !cfg.ignore_proxies && status?.proxyDetected
101
+ return cfg && !cfg.proxies && status?.proxyDetected
102
}
src/adminApis.ts
+1
-1
@@ -165,7 +165,7 @@ export const favicon = defineConfig('favicon', '')
165
export const title = defineConfig('title', "File server")
166
167
export function ctxAdminAccess(ctx: Koa.Context) {
168
- return !ctx.state.proxiedFor // we consider localhost_admin only if no proxy is detected
168
+ return !ctx.ips.length // we consider localhost_admin only if no proxy is being usedø
169
&& localhostAdmin.get() && isLocalHost(ctx)
170
|| getFromAccount(ctx.state.account, a => a.admin)
171
}
src/middlewares.ts
+17
-12
@@ -4,11 +4,11 @@ import compress from 'koa-compress'
4
import Koa from 'koa'
5
import session from 'koa-session'
6
import {
7
- ADMIN_URI,
7
+ ADMIN_URI, API_URI,
8
BUILD_TIMESTAMP,
9
- DEV,
9
+ DEV, DAY,
10
SESSION_DURATION,
11
- HTTP_FORBIDDEN, HTTP_NOT_FOUND, HTTP_FOOL, API_URI,
11
+ HTTP_FORBIDDEN, HTTP_NOT_FOUND, HTTP_FOOL,
12
} from './const'
13
import { FRONTEND_URI } from './const'
14
import { statusCodeForMissingPerm, nodeIsDirectory, urlToNode, vfs } from './vfs'
@@ -34,6 +34,7 @@ import { getHttpsWorkingPort } from './listen'
34
import { defineConfig } from './config'
35
36
const forceHttps = defineConfig('force_https', true)
37
+const ignoreProxies = defineConfig('ignore_proxies', false)
38
39
export const gzipper = compress({
40
threshold: 2048,
@@ -148,20 +149,21 @@ export const serveGuiAndSharedFiles: Koa.Middleware = async (ctx, next) => {
149
: serveFrontendFiles(ctx, next)
150
}
151
151
-let proxyDetected = false
152
+let proxyDetected: undefined | Koa.Context
153
export const someSecurity: Koa.Middleware = async (ctx, next) => {
154
ctx.request.ip = normalizeIp(ctx.ip)
155
try {
155
- let proxy = ctx.get('X-Forwarded-For')
156
- // we have some dev-proxies to ignore
157
- if (DEV && proxy && [process.env.FRONTEND_PROXY, process.env.ADMIN_PROXY].includes(ctx.get('X-Forwarded-port')))
158
- proxy = ''
156
if (dirTraversal(decodeURI(ctx.path)))
157
return ctx.status = HTTP_FOOL
158
if (applyBlock(ctx.socket, ctx.ip))
159
return
163
- proxyDetected ||= proxy > ''
164
- ctx.state.proxiedFor = proxy
160
+
161
+ if (!ctx.ips.length && ctx.get('X-Forwarded-For') // empty ctx.ips implies we didn't configure for proxies
162
+ // we have some dev-proxies to ignore
163
+ && !(DEV && [process.env.FRONTEND_PROXY, process.env.ADMIN_PROXY].includes(ctx.get('X-Forwarded-port')))) {
164
+ proxyDetected = ctx
165
+ ctx.state.when = new Date()
166
+ }
167
}
168
catch {
169
return ctx.status = HTTP_FOOL
@@ -169,9 +171,12 @@ export const someSecurity: Koa.Middleware = async (ctx, next) => {
171
return next()
172
}
173
172
-// this is only about http proxies
174
+// limited to http proxies
175
export function getProxyDetected() {
174
- return proxyDetected
176
+ if (proxyDetected?.state.when < Date.now() - DAY)
177
+ proxyDetected = undefined
178
+ return !ignoreProxies.get() && proxyDetected
179
+ && { from: proxyDetected.ip, for: proxyDetected.get('X-Forwarded-For') }
180
}
181
export const prepareState: Koa.Middleware = async (ctx, next) => {
182
// calculate these once and for all