admin/home: warn FRP users

Massimo Melina committed Apr 13, 2022 at 22:17 UTC f3dff992dd04c360ef925c59c79cf1c2ffa86172
4 files changed +24 -4
admin/src/HomePage.ts
+7 -1
@@ -60,6 +60,12 @@ export default function HomePage() {
60 reloadCfg()
61 }
62 }, "ignore this warning")),
63 + status.frpDetected && entry('warning', `FRP is detected. It should not be used with "type = tcp" with HFS. Possible solutions are`,
64 + h('ol',{},
65 + h('li',{}, `configure FRP with type=http (best solution)`),
66 + h('li',{}, md(`configure FRP to connect to HFS _not_ with 127.0.0.1 (safe, but you won't see users' IPs)`)),
67 + h('li',{}, `disable "admin access for localhost" in HFS (safe, but you won't see users' IPs)`),
68 + ))
69 )
70 }
71
@@ -85,5 +91,5 @@ function cfgLink(text=`Configuration page`) {
91 }
92
93 export function proxyWarning(cfg: any, status: any) {
88 - return cfg && !cfg.proxies && !cfg.ignore_proxies && status?.proxyDetected
94 + return cfg && !cfg.proxies && !cfg.ignore_proxies && status.proxyDetected
95 }
admin/src/index.css
+2
@@ -17,3 +17,5 @@ code {
17 .MuiTreeItem-content {
18 box-sizing: border-box; /* avoid unwanted scrolling caused by its width:100% + padding */
19 }
20 +
21 +ol, ul { margin-top: .2em }
server/src/adminApis.ts
+14 -3
@@ -3,11 +3,11 @@
3 import { ApiError, ApiHandlers } from './apiMiddleware'
4 import { defineConfig, getConfig, getWholeConfig, setConfig } from './config'
5 import { getStatus, getUrls } from './listen'
6 -import { BUILD_TIMESTAMP, FORBIDDEN, HFS_STARTED, VERSION } from './const'
6 +import { BUILD_TIMESTAMP, FORBIDDEN, HFS_STARTED, IS_WINDOWS, VERSION } from './const'
7 import vfsApis from './api.vfs'
8 import accountsApis from './api.accounts'
9 import { Connection, getConnections } from './connections'
10 -import { isLocalHost, onOff, pendingPromise } from './misc'
10 +import { debounceAsync, isLocalHost, onOff, pendingPromise } from './misc'
11 import _ from 'lodash'
12 import events from './events'
13 import { getFromAccount } from './perm'
@@ -19,6 +19,8 @@ import { createReadStream } from 'fs'
19 import * as readline from 'readline'
20 import { loggers } from './log'
21 import { mapPlugins, getAvailablePlugins, Plugin } from './plugins'
22 +import { execFile } from 'child_process'
23 +import { promisify } from 'util'
24
25 export const adminApis: ApiHandlers = {
26
@@ -51,7 +53,10 @@ export const adminApis: ApiHandlers = {
53 https: serverStatus(st.httpsSrv, getConfig('https_port')),
54 urls: getUrls(),
55 proxyDetected: getProxyDetected(),
54 - }
56 + frpDetected: getConfig('localhost_admin') && !getProxyDetected()
57 + && getConnections().every(c => isLocalHost(c.ctx || c.socket.remoteAddress || ''))
58 + && await frpDebounced(),
59 + }
60
61 function serverStatus(h: typeof st.httpSrv, configuredPort?: number) {
62 return {
@@ -212,3 +217,9 @@ export function ctxAdminAccess(ctx: Koa.Context) {
217 && !ctx.state.proxiedFor // this may detect an http-proxied request on localhost
218 || getFromAccount(ctx.state.account, a => a.admin)
219 }
220 +
221 +const frpDebounced = debounceAsync(async () => {
222 + if (!IS_WINDOWS) return false
223 + const { stdout } = await promisify(execFile)('tasklist', ['/fi','imagename eq frpc.exe','/nh'])
224 + return stdout.includes('frpc')
225 +})
server/src/middlewares.ts
+1
@@ -111,6 +111,7 @@ export const someSecurity: Koa.Middleware = async (ctx, next) => {
111 return next()
112 }
113
114 +// this is only about http proxies
115 export function getProxyDetected() {
116 return proxyDetected
117 }