mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-10 23:25:02 +03:00
fix(server): apply the outbound address policy to remote cert pinning
The remote certificate fetch now dials through the same netsafe guard as the REALITY target scan. A private or loopback endpoint is refused unless the request carries allowPrivate; the inbound form asks the operator to confirm and retries with the opt-in.
This commit is contained in:
@@ -398,7 +398,7 @@ export default function TlsForm({
|
||||
/>
|
||||
<Button
|
||||
icon={<CloudDownloadOutlined />}
|
||||
onClick={pinFromRemote}
|
||||
onClick={() => pinFromRemote()}
|
||||
loading={saving}
|
||||
title={t('pages.inbounds.form.pinFromRemote')}
|
||||
/>
|
||||
|
||||
@@ -251,7 +251,7 @@ export function useSecurityActions({
|
||||
* remote certificate hash via `xray tls ping`. Useful when the panel doesn't
|
||||
* hold the cert file (a CDN front / external endpoint).
|
||||
*/
|
||||
const pinFromRemote = async () => {
|
||||
const pinFromRemote = async (allowPrivate = false) => {
|
||||
const server = (
|
||||
(getValues('streamSettings.tlsSettings.serverName') as string | undefined) ?? ''
|
||||
).trim();
|
||||
@@ -268,7 +268,23 @@ export function useSecurityActions({
|
||||
const target = /:\d+$/.test(server) || !port ? server : `${server}:${port}`;
|
||||
setSaving(true);
|
||||
try {
|
||||
const msg = await HttpUtil.post('/panel/api/server/getRemoteCertHash', { server: target });
|
||||
const msg = await HttpUtil.post(
|
||||
'/panel/api/server/getRemoteCertHash',
|
||||
{ server: target, allowPrivate },
|
||||
{ silent: true },
|
||||
);
|
||||
// The SSRF guard refuses a LAN/loopback endpoint until the operator confirms it.
|
||||
const blocked = (msg?.obj as { privateTarget?: boolean } | null | undefined)?.privateTarget;
|
||||
if (!msg?.success && blocked && !allowPrivate) {
|
||||
modal.confirm({
|
||||
title: t('pages.inbounds.form.scanPrivateConfirmTitle'),
|
||||
content: t('pages.inbounds.form.scanPrivateConfirmContent', { target }),
|
||||
okText: t('confirm'),
|
||||
cancelText: t('cancel'),
|
||||
onOk: () => pinFromRemote(true),
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!msg?.success) {
|
||||
messageApi.warning(msg?.msg || t('pages.inbounds.form.pinFromRemoteFailed'));
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user