diff --git a/install.sh b/install.sh index b3537eed..a53b6657 100644 --- a/install.sh +++ b/install.sh @@ -132,24 +132,15 @@ NODE_TYPE=${INPUT_TYPE:-${NODE_TYPE:-v2ray}} read -p "Enter Panel Token (Node Key) [${PANEL_TOKEN}]: " INPUT_TOKEN PANEL_TOKEN=${INPUT_TOKEN:-$PANEL_TOKEN} -# Optional Separate Config/User IDs and URLs -read -p "Use separate URL/ID for Config? (y/N): " USE_SEP_CONFIG -if [[ "$USE_SEP_CONFIG" =~ ^[Yy]$ ]]; then - read -p " Enter Config Panel URL [${CONFIG_PANEL_URL:-$PANEL_URL}]: " INPUT_CURL - CONFIG_PANEL_URL=${INPUT_CURL:-$PANEL_URL} - CONFIG_PANEL_URL="${CONFIG_PANEL_URL%/}" - read -p " Enter Config Node ID [${CONFIG_NODE_ID:-$NODE_ID}]: " INPUT_CID - CONFIG_NODE_ID=${INPUT_CID:-$NODE_ID} -fi +# Consolidation +CONFIG_PANEL_URL=$PANEL_URL +CONFIG_NODE_ID=$NODE_ID +USER_PANEL_URL=$PANEL_URL +USER_NODE_ID=$NODE_ID -read -p "Use separate URL/ID for Users? (y/N): " USE_SEP_USER -if [[ "$USE_SEP_USER" =~ ^[Yy]$ ]]; then - read -p " Enter User Panel URL [${USER_PANEL_URL:-$PANEL_URL}]: " INPUT_UURL - USER_PANEL_URL=${INPUT_UURL:-$PANEL_URL} - USER_PANEL_URL="${USER_PANEL_URL%/}" - read -p " Enter User Node ID [${USER_NODE_ID:-$NODE_ID}]: " INPUT_UID - USER_NODE_ID=${INPUT_UID:-$NODE_ID} -fi +# Sync time (Critical for SS 2022) +echo -e "${YELLOW}Syncing system time...${NC}" +timedatectl set-ntp true || true if [[ -z "$PANEL_URL" || -z "$NODE_ID" || -z "$PANEL_TOKEN" ]]; then echo -e "${RED}All fields are required!${NC}" diff --git a/service/xboard/service.go b/service/xboard/service.go index c82ef6c4..0c0a305e 100644 --- a/service/xboard/service.go +++ b/service/xboard/service.go @@ -29,13 +29,24 @@ func fixSSKey(key string, length int) string { if key == "" { return "" } - // Try to decode as-is first + // If it's already a valid Base64 of the correct length, use it directly (as a B64 key) if data, err := base64.StdEncoding.DecodeString(key); err == nil && len(data) == length { return key } - // Use SHA256 to derive a fixed-length key from the password - hash := sha256.Sum256([]byte(key)) - return base64.StdEncoding.EncodeToString(hash[:length]) + + // Legacy repetition/truncation logic for raw string keys (common in Xboard/V2board) + password := key + if len(password) > length { + password = password[:length] + } + for len(password) < length { + password += password + } + // Re-truncate after repetition + password = password[:length] + + // Convert to Base64 so sing-box treats it as a raw byte key + return base64.StdEncoding.EncodeToString([]byte(password)) } func RegisterService(registry *boxService.Registry) { @@ -406,6 +417,17 @@ func (s *Service) fetchConfig() (*XNodeConfig, error) { return nil, err } defer resp.Body.Close() + + // Check time drift + if dateStr := resp.Header.Get("Date"); dateStr != "" { + if panelTime, err := http.ParseTime(dateStr); err == nil { + drift := time.Since(panelTime) + if drift < 0 { drift = -drift } + if drift > 30*time.Second { + s.logger.Error("CRITICAL TIME DRIFT: ", drift, " off from Panel. SS 2022 WILL FAIL. Sync your time!") + } + } + } if resp.StatusCode != 200 { respBody, _ := io.ReadAll(resp.Body)