feat(xo-server): http.useForwardedHeaders (#7233)
Fixes https://xcp-ng.org/forum/post/67625 This setting can be enabled when XO is behind a reverse proxy to fetch clients IP addresses from `X-Forwarded-*` headers.
This commit is contained in:
parent
bee0eb9091
commit
b7daee81c0
@ -13,6 +13,7 @@
|
||||
- [REST API] _XO config & Pool metadata Backup_ jobs are available at `/backup/jobs/metadata`
|
||||
- [REST API] _Mirror Backup_ jobs are available at `/backup/jobs/metadata`
|
||||
- [Plugin/auth-saml] Add _Force re-authentication_ setting [Forum#67764](https://xcp-ng.org/forum/post/67764) (PR [#7232](https://github.com/vatesfr/xen-orchestra/pull/7232))
|
||||
- [HTTP] `http.useForwardedHeaders` setting can be enabled when XO is behind a reverse proxy to fetch clients IP addresses from `X-Forwarded-*` headers [Forum#67625](https://xcp-ng.org/forum/post/67625) (PR [#7233](https://github.com/vatesfr/xen-orchestra/pull/7233))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
@ -107,6 +107,9 @@ writeBlockConcurrency = 16
|
||||
enabled = false
|
||||
threshold = 1000
|
||||
|
||||
[http]
|
||||
useForwardedHeaders = false
|
||||
|
||||
# Helmet handles HTTP security via headers
|
||||
#
|
||||
# https://helmetjs.github.io/docs/
|
||||
|
@ -107,6 +107,7 @@
|
||||
"passport": "^0.6.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"promise-toolbox": "^0.21.0",
|
||||
"proxy-addr": "^2.0.7",
|
||||
"proxy-agent": "^5.0.0",
|
||||
"pug": "^3.0.0",
|
||||
"pumpify": "^2.0.0",
|
||||
|
@ -72,6 +72,20 @@
|
||||
# good enough (e.g. a domain name must be used or there is a reverse proxy).
|
||||
#publicUrl = 'https://xoa.company.lan'
|
||||
|
||||
# Uncomment this if xo-server is behind a reverse proxy to make xo-server use
|
||||
# X-Forwarded-* headers to determine the IP address of clients.
|
||||
#
|
||||
# Accepted values for this setting:
|
||||
# - false (default): do not use the headers
|
||||
# - true: always use the headers
|
||||
# - a list of trusted addresses: the headers will be used only if the connection
|
||||
# is coming from one of these addresses
|
||||
#
|
||||
# More info about the accepted values: https://www.npmjs.com/package/proxy-addr?activeTab=readme#proxyaddrreq-trust
|
||||
#
|
||||
# > Note: X-Forwarded-* headers are easily spoofed and the detected IP addresses are unreliable.
|
||||
#useForwardedHeaders = true
|
||||
|
||||
# Settings applied to cookies created by xo-server's embedded HTTP server.
|
||||
#
|
||||
# See https://www.npmjs.com/package/cookie#options-1
|
||||
|
@ -13,6 +13,7 @@ import memoryStoreFactory from 'memorystore'
|
||||
import merge from 'lodash/merge.js'
|
||||
import ms from 'ms'
|
||||
import once from 'lodash/once.js'
|
||||
import proxyAddr from 'proxy-addr'
|
||||
import proxyConsole from './proxy-console.mjs'
|
||||
import pw from 'pw'
|
||||
import serveStatic from 'serve-static'
|
||||
@ -584,7 +585,7 @@ const setUpStaticFiles = (express, opts) => {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
const setUpApi = (webServer, xo, config) => {
|
||||
const setUpApi = (webServer, xo, config, useForwardedHeaders) => {
|
||||
const webSocketServer = new WebSocketServer({
|
||||
...config.apiWebSocketOptions,
|
||||
|
||||
@ -593,7 +594,7 @@ const setUpApi = (webServer, xo, config) => {
|
||||
xo.hooks.on('stop', () => fromCallback.call(webSocketServer, 'close'))
|
||||
|
||||
const onConnection = (socket, upgradeReq) => {
|
||||
const { remoteAddress } = upgradeReq.socket
|
||||
const remoteAddress = proxyAddr(upgradeReq, useForwardedHeaders)
|
||||
|
||||
// Create the abstract XO object for this connection.
|
||||
const connection = xo.createApiConnection(remoteAddress)
|
||||
@ -653,7 +654,7 @@ const setUpApi = (webServer, xo, config) => {
|
||||
|
||||
const CONSOLE_PROXY_PATH_RE = /^\/api\/consoles\/(.*)$/
|
||||
|
||||
const setUpConsoleProxy = (webServer, xo) => {
|
||||
const setUpConsoleProxy = (webServer, xo, useForwardedHeaders) => {
|
||||
const webSocketServer = new WebSocketServer({
|
||||
noServer: true,
|
||||
})
|
||||
@ -678,7 +679,7 @@ const setUpConsoleProxy = (webServer, xo) => {
|
||||
throw invalidCredentials()
|
||||
}
|
||||
|
||||
const { remoteAddress } = socket
|
||||
const remoteAddress = proxyAddr(req, useForwardedHeaders)
|
||||
log.info(`+ Console proxy (${user.name} - ${remoteAddress})`)
|
||||
|
||||
const data = {
|
||||
@ -836,8 +837,20 @@ export default async function main(args) {
|
||||
// Trigger a clean job.
|
||||
await xo.hooks.clean()
|
||||
|
||||
const useForwardedHeaders = (() => {
|
||||
// recompile the fonction when the setting change
|
||||
let useForwardedHeaders
|
||||
xo.config.watch('http.useForwardedHeaders', val => {
|
||||
useForwardedHeaders = typeof val === 'boolean' ? () => val : proxyAddr.compile(val)
|
||||
})
|
||||
|
||||
return (...args) => useForwardedHeaders(...args)
|
||||
})()
|
||||
|
||||
express.set('trust proxy', useForwardedHeaders)
|
||||
|
||||
// Must be set up before the API.
|
||||
setUpConsoleProxy(webServer, xo)
|
||||
setUpConsoleProxy(webServer, xo, useForwardedHeaders)
|
||||
|
||||
// Must be set up before the API.
|
||||
express.use(xo._handleHttpRequest.bind(xo))
|
||||
@ -847,7 +860,7 @@ export default async function main(args) {
|
||||
await setUpPassport(express, xo, config)
|
||||
|
||||
// Must be set up before the static files.
|
||||
setUpApi(webServer, xo, config)
|
||||
setUpApi(webServer, xo, config, useForwardedHeaders)
|
||||
|
||||
setUpProxies(express, config.http.proxies, xo)
|
||||
|
||||
|
@ -17225,7 +17225,7 @@ protocol-buffers-encodings@^1.1.0:
|
||||
signed-varint "^2.0.1"
|
||||
varint "5.0.0"
|
||||
|
||||
proxy-addr@~2.0.7:
|
||||
proxy-addr@^2.0.7, proxy-addr@~2.0.7:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
|
||||
integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
|
||||
|
Loading…
Reference in New Issue
Block a user