Odchozi IP adresa portalu

Kdyz cizi sluzba odmitne pristup, prvni otazka je, z jake adresy se vlastne
vola. Z containeru to videt neni, vidi to az protistrana, takze se zepta echo
sluzby podle EGRESS_IP_URL a vysledek se drzi v pameti po EGRESS_IP_TTL_MS.
Prazdna EGRESS_IP_URL funkci vypne, prepsat ji jde na vlastni echo pod svou
domenou.

Adresa je natvrdo na strance Konektory a u kazdeho odmitnuteho overeni v logu.
Pripojuje se jen u 401 a 403 - jinde nema co rict a nestoji za volani ven.

Neni to tajemstvi: kazda volana sluzba tuhle adresu stejne vidi.

Endpoint egress-ip je registrovany pred GET /:id, jinak by ho router vzal
jako id konektoru.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
JiriUhlir
2026-08-25 07:22:26 +02:00
co-authored by Claude Opus 5
parent ab88979627
commit 4545de8076
9 changed files with 283 additions and 0 deletions
+25
View File
@@ -40,6 +40,7 @@ import {
type Service,
} from '../data/services.js';
import { config } from '../config.js';
import { egressIp } from '../data/egressIp.js';
import { resolveTarget, serviceBaseUrl } from '../scripts/connections.js';
import { createHttp } from '../scripts/http.js';
import { ScriptError } from '../scripts/types.js';
@@ -120,6 +121,21 @@ connectorsRouter.get('/services', async (req, res) => {
res.json({ categories: serviceCategories, items, tenantId: tenantId ?? null });
});
/**
* Odchozi IP adresa portalu.
*
* Kdyz cizi sluzba odmitne pristup, prvni otazka je "z jake adresy jsme
* vlastne volali". Z containeru to videt neni, vidi to az protistrana,
* takze se zepta echo sluzby (`EGRESS_IP_URL`). Vysledek se drzi v pameti.
*
* Neni to tajemstvi ani nic, co by slo zneuzit - je to adresa, kterou kazda
* volana sluzba stejne vidi.
*/
connectorsRouter.get('/egress-ip', async (req, res) => {
if (!tenantOrDeny(req, res)) return;
return res.json(await egressIp());
});
// ----------------------------------------------------------------- konektory
connectorsRouter.get('/', async (req, res) => {
@@ -290,6 +306,7 @@ connectorsRouter.post('/:id/test', async (req, res) => {
detail: null,
request: null,
responseHeaders: null,
egressIp: null,
},
[tenantId],
);
@@ -336,6 +353,7 @@ connectorsRouter.post('/:id/test', async (req, res) => {
detail: null,
request,
responseHeaders: null,
egressIp: null,
},
[tenantId],
);
@@ -364,6 +382,11 @@ connectorsRouter.post('/:id/test', async (req, res) => {
// Hlavicky rikaji, kdo odpoved vydal. U 403 bez tela je to vsechno,
// co zbyde: `Server: Kestrel` je aplikace, `Via: 1.1 Caddy` proxy.
const responseHeaders = isScriptError ? (err.responseHeaders ?? null) : null;
// Odmitnuty pristup je jediny pripad, kdy je odchozi IP podstatna: cizi
// sluzba ma seznam povolenych adres a z containeru neni videt, jak ho
// protistrana vidi. Z pameti, takze to volani ven vetsinou nestoji nic.
const egress = status === 401 || status === 403 ? (await egressIp()).ip : null;
const check: ConnectorCheck = {
at: new Date().toISOString(),
ok: false,
@@ -373,6 +396,7 @@ connectorsRouter.post('/:id/test', async (req, res) => {
detail: detail ?? null,
request,
responseHeaders,
egressIp: egress,
};
await setConnectorStatus(connector.id, 'error', message, check, [tenantId]);
@@ -387,6 +411,7 @@ connectorsRouter.post('/:id/test', async (req, res) => {
request,
baseUrl: target.baseUrl,
...(responseHeaders ? { responseHeaders } : {}),
...(egress ? { egressIp: egress } : {}),
...(detail ? { detail } : {}),
});
} finally {