소스 검색

fix(tls): ping the inbound's own port for remote cert pinning

The pin-from-remote button passed only the SNI to 'xray tls ping', which defaults to :443 — so it never reached a self-hosted inbound on another port and failed with a vague 'no certificate hash found'. Append the inbound's port when the SNI carries none, and surface the underlying ping failure (dial refused, timeout) in the error.
MHSanaei 16 시간 전
부모
커밋
03e89683dd
2개의 변경된 파일15개의 추가작업 그리고 1개의 파일을 삭제
  1. 6 1
      frontend/src/pages/inbounds/form/useSecurityActions.ts
  2. 9 0
      internal/web/service/server.go

+ 6 - 1
frontend/src/pages/inbounds/form/useSecurityActions.ts

@@ -143,9 +143,14 @@ export function useSecurityActions({ form, setSaving, messageApi, nodeId }: UseS
       messageApi.warning(t('pages.inbounds.form.pinFromRemoteNoSni'));
       return;
     }
+    // `xray tls ping` defaults to :443, but a self-hosted inbound rarely
+    // listens there. Append the inbound's own port (unless the SNI already
+    // carries one) so the ping reaches the actual TLS endpoint.
+    const port = form.getFieldValue('port') as number | undefined;
+    const target = /:\d+$/.test(server) || !port ? server : `${server}:${port}`;
     setSaving(true);
     try {
-      const msg = await HttpUtil.post('/panel/api/server/getRemoteCertHash', { server });
+      const msg = await HttpUtil.post('/panel/api/server/getRemoteCertHash', { server: target });
       if (!msg?.success) {
         messageApi.warning(msg?.msg || t('pages.inbounds.form.pinFromRemoteFailed'));
         return;

+ 9 - 0
internal/web/service/server.go

@@ -1896,6 +1896,15 @@ func (s *ServerService) GetRemoteCertHash(server string) ([]string, error) {
 		}
 	}
 	if len(leaves) == 0 {
+		// Surface why the ping produced no cert (dial refused, timeout, …)
+		// instead of the bare "not found" — the inbound is usually just not
+		// listening for TLS on the pinged port.
+		for _, line := range strings.Split(out.String(), "\n") {
+			line = strings.TrimSpace(line)
+			if strings.Contains(line, "Failed") || strings.Contains(line, "error") {
+				return nil, common.NewError("no certificate hash for ", server, ": ", line)
+			}
+		}
 		return nil, common.NewError("no certificate hash found for ", server)
 	}
 	return leaves, nil