Merge pull request #127 from ReturnFI/beta

Change pinSHA256 to Hex
Deprecated SingBox SubLink
This commit is contained in:
Whispering Wind
2025-04-11 22:29:30 +03:30
committed by GitHub
12 changed files with 131 additions and 118 deletions

View File

@ -5,7 +5,7 @@
[![Lang_Eglish](https://img.shields.io/badge/Language-English-009688?logo=google-translate&logoColor=white)](README.md) [![Lang_Eglish](https://img.shields.io/badge/Language-English-009688?logo=google-translate&logoColor=white)](README.md)
[![Latest Release](https://img.shields.io/badge/Release-Latest-brightgreen?logo=github)](https://github.com/ReturnFI/Hysteria2/releases) [![Latest Release](https://img.shields.io/badge/Release-Latest-brightgreen?logo=github)](https://github.com/ReturnFI/Hysteria2/releases)
[![License](https://img.shields.io/badge/License-MIT-blueviolet?logo=open-source-initiative&logoColor=white)](LICENSE) [![License](https://img.shields.io/badge/License-GPL-blueviolet?logo=open-source-initiative&logoColor=white)](LICENSE)
[![Made with ❤️](https://img.shields.io/badge/Made%20with-%E2%9D%A4-red)](#) [![Made with ❤️](https://img.shields.io/badge/Made%20with-%E2%9D%A4-red)](#)

View File

@ -5,7 +5,7 @@
[![Language](https://img.shields.io/badge/Language-Persian-009688?logo=google-translate&logoColor=white)](README-fa.md) [![Language](https://img.shields.io/badge/Language-Persian-009688?logo=google-translate&logoColor=white)](README-fa.md)
[![Latest Release](https://img.shields.io/badge/Release-Latest-brightgreen?logo=github)](https://github.com/ReturnFI/Hysteria2/releases) [![Latest Release](https://img.shields.io/badge/Release-Latest-brightgreen?logo=github)](https://github.com/ReturnFI/Hysteria2/releases)
[![License](https://img.shields.io/badge/License-MIT-blueviolet?logo=open-source-initiative&logoColor=white)](LICENSE) [![License](https://img.shields.io/badge/License-GPL-blueviolet?logo=open-source-initiative&logoColor=white)](LICENSE)
[![Made with ❤️](https://img.shields.io/badge/Made%20with-%E2%9D%A4-red)](#) [![Made with ❤️](https://img.shields.io/badge/Made%20with-%E2%9D%A4-red)](#)

View File

@ -1,7 +1,5 @@
## [1.5.0] - 2025-04-11 ## [1.5.1] - 2025-04-11
### Added
- Integrated Hysteria2-API package (https://github.com/ReturnFI/Hysteria2-API)
- Added support for managing traffic file via API
### Changed ### Changed
- Refactored traffic-related logic to use the new API package - Deprecated SingBox SubLink
- Change pinSHA256 to Hex

View File

@ -19,25 +19,26 @@ update_sni() {
openssl req -new -x509 -days 36500 -key ca.key -out ca.crt -subj "/CN=$sni" >/dev/null 2>&1 openssl req -new -x509 -days 36500 -key ca.key -out ca.crt -subj "/CN=$sni" >/dev/null 2>&1
chown hysteria:hysteria /etc/hysteria/ca.key /etc/hysteria/ca.crt chown hysteria:hysteria /etc/hysteria/ca.key /etc/hysteria/ca.crt
chmod 640 /etc/hysteria/ca.key /etc/hysteria/ca.crt chmod 640 /etc/hysteria/ca.key /etc/hysteria/ca.crt
fingerprint=$(openssl x509 -noout -fingerprint -sha256 -inform pem -in ca.crt | sed 's/.*=//;s/://g') sha256=$(openssl x509 -noout -fingerprint -sha256 -inform pem -in ca.crt | sed 's/.*=//;s///g')
sha256=$(python3 - <<EOF # sha256=$(python3 - <<EOF
import base64 # import base64
import binascii # import binascii
# Hexadecimal string # # Hexadecimal string
hex_string = "$fingerprint" # hex_string = "$fingerprint"
# Convert hex to binary # # Convert hex to binary
binary_data = binascii.unhexlify(hex_string) # binary_data = binascii.unhexlify(hex_string)
# Encode binary data to base64 # # Encode binary data to base64
base64_encoded = base64.b64encode(binary_data).decode('utf-8') # base64_encoded = base64.b64encode(binary_data).decode('utf-8')
# # Print the result prefixed with 'sha256/'
# print('sha256/' + base64_encoded)
# EOF
# )
# Print the result prefixed with 'sha256/'
print('sha256/' + base64_encoded)
EOF
)
echo "SHA-256 fingerprint generated: $sha256" echo "SHA-256 fingerprint generated: $sha256"
if [ -f "$CONFIG_FILE" ]; then if [ -f "$CONFIG_FILE" ]; then

View File

@ -19,27 +19,27 @@ install_hysteria() {
wget -O /etc/hysteria/geosite.dat https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geosite.dat >/dev/null 2>&1 wget -O /etc/hysteria/geosite.dat https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geosite.dat >/dev/null 2>&1
wget -O /etc/hysteria/geoip.dat https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geoip.dat >/dev/null 2>&1 wget -O /etc/hysteria/geoip.dat https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geoip.dat >/dev/null 2>&1
fingerprint=$(openssl x509 -noout -fingerprint -sha256 -inform pem -in ca.crt | sed 's/.*=//;s/://g') # fingerprint=$(openssl x509 -noout -fingerprint -sha256 -inform pem -in ca.crt | sed 's/.*=//;s/://g')
echo "Generating base64 encoded SHA-256 fingerprint..." echo "Generating base64 encoded SHA-256 fingerprint..."
cat <<EOF > generate.py # cat <<EOF > generate.py
import base64 # import base64
import binascii # import binascii
# Hexadecimal string # # Hexadecimal string
hex_string = "$fingerprint" # hex_string = "$fingerprint"
# Convert hex to binary # # Convert hex to binary
binary_data = binascii.unhexlify(hex_string) # binary_data = binascii.unhexlify(hex_string)
# Encode binary data to base64 # # Encode binary data to base64
base64_encoded = base64.b64encode(binary_data).decode('utf-8') # base64_encoded = base64.b64encode(binary_data).decode('utf-8')
# Print the result prefixed with 'sha256/' # # Print the result prefixed with 'sha256/'
print('sha256/' + base64_encoded) # print('sha256/' + base64_encoded)
EOF # EOF
sha256=$(python3 generate.py) sha256=$(openssl x509 -noout -fingerprint -sha256 -inform pem -in ca.crt | sed 's/.*=//;s///g')
if [[ $port =~ ^[0-9]+$ ]] && (( port >= 1 && port <= 65535 )); then if [[ $port =~ ^[0-9]+$ ]] && (( port >= 1 && port <= 65535 )); then
if ss -tuln | grep -q ":$port\b"; then if ss -tuln | grep -q ":$port\b"; then

View File

@ -6,7 +6,7 @@ declare -a services=(
"hysteria-caddy.service" "hysteria-caddy.service"
"hysteria-telegram-bot.service" "hysteria-telegram-bot.service"
"hysteria-normal-sub.service" "hysteria-normal-sub.service"
"hysteria-singbox.service" # "hysteria-singbox.service"
"hysteria-ip-limit.service" "hysteria-ip-limit.service"
"wg-quick@wgcf.service" "wg-quick@wgcf.service"
) )

View File

@ -87,15 +87,15 @@ def process_show_user(message):
result_lines = combined_result.strip().split('\n') result_lines = combined_result.strip().split('\n')
uri_v4 = "" uri_v4 = ""
singbox_sublink = "" # singbox_sublink = ""
normal_sub_sublink = "" normal_sub_sublink = ""
for line in result_lines: for line in result_lines:
line = line.strip() line = line.strip()
if line.startswith("hy2://"): if line.startswith("hy2://"):
uri_v4 = line uri_v4 = line
elif line.startswith("Singbox Sublink:"): # elif line.startswith("Singbox Sublink:"):
singbox_sublink = result_lines[result_lines.index(line) + 1].strip() # singbox_sublink = result_lines[result_lines.index(line) + 1].strip()
elif line.startswith("Normal-SUB Sublink:"): elif line.startswith("Normal-SUB Sublink:"):
normal_sub_sublink = result_lines[result_lines.index(line) + 1].strip() normal_sub_sublink = result_lines[result_lines.index(line) + 1].strip()
@ -119,8 +119,8 @@ def process_show_user(message):
types.InlineKeyboardButton("Block User", callback_data=f"block_user:{actual_username}")) types.InlineKeyboardButton("Block User", callback_data=f"block_user:{actual_username}"))
caption = f"{formatted_details}\n\n**IPv4 URI:**\n\n`{uri_v4}`" caption = f"{formatted_details}\n\n**IPv4 URI:**\n\n`{uri_v4}`"
if singbox_sublink: # if singbox_sublink:
caption += f"\n\n**SingBox SUB:**\n{singbox_sublink}" # caption += f"\n\n**SingBox SUB:**\n{singbox_sublink}"
if normal_sub_sublink: if normal_sub_sublink:
caption += f"\n\n**Normal SUB:**\n{normal_sub_sublink}" caption += f"\n\n**Normal SUB:**\n{normal_sub_sublink}"

View File

@ -20,7 +20,7 @@ class ServerServicesStatusResponse(BaseModel):
hysteria_server: bool hysteria_server: bool
hysteria_webpanel: bool hysteria_webpanel: bool
hysteria_iplimit: bool hysteria_iplimit: bool
hysteria_singbox: bool # hysteria_singbox: bool
hysteria_normal_sub: bool hysteria_normal_sub: bool
hysteria_telegram_bot: bool hysteria_telegram_bot: bool
hysteria_warp: bool hysteria_warp: bool

View File

@ -141,8 +141,8 @@ def __parse_services_status(services_status: dict[str, bool]) -> ServerServicesS
parsed_services_status['hysteria_telegram_bot'] = status parsed_services_status['hysteria_telegram_bot'] = status
elif 'hysteria-normal-sub' in service: elif 'hysteria-normal-sub' in service:
parsed_services_status['hysteria_normal_sub'] = status parsed_services_status['hysteria_normal_sub'] = status
elif 'hysteria-singbox' in service: # elif 'hysteria-singbox' in service:
parsed_services_status['hysteria_singbox'] = status # parsed_services_status['hysteria_singbox'] = status
elif 'wg-quick' in service: elif 'wg-quick' in service:
parsed_services_status['hysteria_warp'] = status parsed_services_status['hysteria_warp'] = status
return ServerServicesStatusResponse(**parsed_services_status) return ServerServicesStatusResponse(**parsed_services_status)

View File

@ -68,19 +68,13 @@
<div class='tab-pane fade show active' id='subs' role='tabpanel' aria-labelledby='subs-tab'> <div class='tab-pane fade show active' id='subs' role='tabpanel' aria-labelledby='subs-tab'>
<ul class='nav nav-tabs' id='subs-tabs' role='tablist'> <ul class='nav nav-tabs' id='subs-tabs' role='tablist'>
<li class='nav-item'> <li class='nav-item'>
<a class='nav-link active' id='singbox-tab' data-toggle='tab' href='#singbox' <a class='nav-link active' id='normal-tab' data-toggle='tab' href='#normal' role='tab'
role='tab' aria-controls='singbox'
aria-selected='true'><strong>SingBox</strong></a>
</li>
<li class='nav-item'>
<a class='nav-link' id='normal-tab' data-toggle='tab' href='#normal' role='tab'
aria-controls='normal' aria-selected='false'><strong>Normal</strong></a> aria-controls='normal' aria-selected='false'><strong>Normal</strong></a>
</li> </li>
</ul> </ul>
<div class='tab-content' id='subs-tabs-content'> <div class='tab-content' id='subs-tabs-content'>
<br> <br>
<!-- SingBox Sub Tab --> <!-- <div class='tab-pane fade show active' id='singbox' role='tabpanel'
<div class='tab-pane fade show active' id='singbox' role='tabpanel'
aria-labelledby='singbox-tab'> aria-labelledby='singbox-tab'>
<form id="singbox"> <form id="singbox">
<div class='form-group'> <div class='form-group'>
@ -107,10 +101,10 @@
style="display: none;">Stop</button> style="display: none;">Stop</button>
</form> </form>
</div> </div> -->
<!-- Normal Sub Tab --> <!-- Normal Sub Tab -->
<div class='tab-pane fade' id='normal' role='tabpanel' aria-labelledby='normal-tab'> <div class='tab-pane fade show active' id='normal' role='tabpanel' aria-labelledby='normal-tab'>
<form id="normal"> <form id="normal">
<div class='form-group'> <div class='form-group'>
<label for='normal_domain'>Domain:</label> <label for='normal_domain'>Domain:</label>
@ -467,7 +461,7 @@
function updateServiceUI(data) { function updateServiceUI(data) {
const servicesMap = { const servicesMap = {
"hysteria_telegram_bot": "#telegram", "hysteria_telegram_bot": "#telegram",
"hysteria_singbox": "#singbox", // "hysteria_singbox": "#singbox", // singbox removed
"hysteria_normal_sub": "#normal", "hysteria_normal_sub": "#normal",
"hysteria_iplimit": "#ip-limit-service" "hysteria_iplimit": "#ip-limit-service"
}; };
@ -483,9 +477,9 @@
$(selector).prepend(`<div class='alert alert-info'>Service is running. You can stop it if needed.</div>`); $(selector).prepend(`<div class='alert alert-info'>Service is running. You can stop it if needed.</div>`);
$(selector + " .btn-danger").show(); $(selector + " .btn-danger").show();
if (service === "hysteria_singbox") { // if (service === "hysteria_singbox") { // singbox removed
$("#singbox_start").prop('disabled', true); // $("#singbox_start").prop('disabled', true);
} // }
if(service === "hysteria_telegram_bot"){ if(service === "hysteria_telegram_bot"){
$("#telegram_start").prop('disabled', true); $("#telegram_start").prop('disabled', true);
} }
@ -508,9 +502,9 @@
$(selector + " .btn-success").show(); $(selector + " .btn-success").show();
$(selector + " .btn-danger").hide(); $(selector + " .btn-danger").hide();
$(selector + " .alert-info").remove(); $(selector + " .alert-info").remove();
if (service === "hysteria_singbox") { // if (service === "hysteria_singbox") { // singbox removed
$("#singbox_start").prop('disabled', false); // $("#singbox_start").prop('disabled', false);
} // }
if(service === "hysteria_telegram_bot"){ if(service === "hysteria_telegram_bot"){
$("#telegram_start").prop('disabled', false); $("#telegram_start").prop('disabled', false);
} }
@ -598,32 +592,32 @@
}); });
} }
function startSingbox() { // function startSingbox() { // singbox removed
if (!validateForm('singbox')) return; // if (!validateForm('singbox')) return;
const domain = $("#singbox_domain").val(); // const domain = $("#singbox_domain").val();
const port = $("#singbox_port").val(); // const port = $("#singbox_port").val();
confirmAction("start SingBox", function () { // confirmAction("start SingBox", function () {
sendRequest( // sendRequest(
"{{ url_for('singbox_start_api') }}", // "{{ url_for('singbox_start_api') }}",
"POST", // "POST",
{ domain: domain, port: port }, // { domain: domain, port: port },
"SingBox started successfully!", // "SingBox started successfully!",
"#singbox_start" // "#singbox_start"
); // );
}); // });
} // }
function stopSingbox() { // function stopSingbox() { // singbox removed
confirmAction("stop SingBox", function () { // confirmAction("stop SingBox", function () {
sendRequest( // sendRequest(
"{{ url_for('singbox_stop_api') }}", // "{{ url_for('singbox_stop_api') }}",
"DELETE", // "DELETE",
null, // null,
"SingBox stopped successfully!", // "SingBox stopped successfully!",
null // null
); // );
}); // });
} // }
function startNormal() { function startNormal() {
if (!validateForm('normal')) return; if (!validateForm('normal')) return;
@ -792,8 +786,8 @@
$("#telegram_start").on("click", startTelegram); $("#telegram_start").on("click", startTelegram);
$("#telegram_stop").on("click", stopTelegram); $("#telegram_stop").on("click", stopTelegram);
$("#singbox_start").on("click", startSingbox); // $("#singbox_start").on("click", startSingbox); // singbox removed
$("#singbox_stop").on("click", stopSingbox); // $("#singbox_stop").on("click", stopSingbox); // singbox removed
$("#normal_start").on("click", startNormal); $("#normal_start").on("click", startNormal);
$("#normal_stop").on("click", stopNormal); $("#normal_stop").on("click", stopNormal);
$("#port_change").on("click", changePort); $("#port_change").on("click", changePort);
@ -806,7 +800,8 @@
$("#ip_limit_change_config").on("click", configIPLimit); $("#ip_limit_change_config").on("click", configIPLimit);
$('#singbox_domain, #normal_domain, #sni_domain').on('input', function () { // $('#singbox_domain, #normal_domain, #sni_domain').on('input', function () { // singbox removed
$('#normal_domain, #sni_domain').on('input', function () {
if (isValidDomain($(this).val())) { if (isValidDomain($(this).val())) {
$(this).removeClass('is-invalid'); $(this).removeClass('is-invalid');
} else { } else {
@ -814,7 +809,8 @@
} }
}); });
$('#singbox_port, #normal_port, #hysteria_port').on('input', function () { // $('#singbox_port, #normal_port, #hysteria_port').on('input', function () { // singbox removed
$('#normal_port, #hysteria_port').on('input', function () {
if (isValidPort($(this).val())) { if (isValidPort($(this).val())) {
$(this).removeClass('is-invalid'); $(this).removeClass('is-invalid');
} else { } else {

55
menu.sh
View File

@ -485,39 +485,40 @@ telegram_bot_handler() {
singbox_handler() { singbox_handler() {
while true; do while true; do
echo -e "${cyan}1.${NC} Start Singbox service" echo -e "${cyan}Merged with Normal-Sub sublink.${NC}"
# echo -e "${cyan}1.${NC} Start Singbox service"
echo -e "${red}2.${NC} Stop Singbox service" echo -e "${red}2.${NC} Stop Singbox service"
echo "0. Back" echo "0. Back"
read -p "Choose an option: " option read -p "Choose an option: " option
case $option in case $option in
1) # 1)
if systemctl is-active --quiet hysteria-singbox.service; then # if systemctl is-active --quiet hysteria-singbox.service; then
echo "The hysteria-singbox.service is already active." # echo "The hysteria-singbox.service is already active."
else # else
while true; do # while true; do
read -e -p "Enter the domain name for the SSL certificate: " domain # read -e -p "Enter the domain name for the SSL certificate: " domain
if [ -z "$domain" ]; then # if [ -z "$domain" ]; then
echo "Domain name cannot be empty. Please try again." # echo "Domain name cannot be empty. Please try again."
else # else
break # break
fi # fi
done # done
while true; do # while true; do
read -e -p "Enter the port number for the service: " port # read -e -p "Enter the port number for the service: " port
if [ -z "$port" ]; then # if [ -z "$port" ]; then
echo "Port number cannot be empty. Please try again." # echo "Port number cannot be empty. Please try again."
elif ! [[ "$port" =~ ^[0-9]+$ ]]; then # elif ! [[ "$port" =~ ^[0-9]+$ ]]; then
echo "Port must be a number. Please try again." # echo "Port must be a number. Please try again."
else # else
break # break
fi # fi
done # done
python3 $CLI_PATH singbox -a start -d "$domain" -p "$port" # python3 $CLI_PATH singbox -a start -d "$domain" -p "$port"
fi # fi
;; # ;;
2) 2)
if ! systemctl is-active --quiet hysteria-singbox.service; then if ! systemctl is-active --quiet hysteria-singbox.service; then
echo "The hysteria-singbox.service is already inactive." echo "The hysteria-singbox.service is already inactive."
@ -1011,7 +1012,7 @@ display_advance_menu() {
echo -e "${cyan}[3] ${NC}↝ Configure WARP" echo -e "${cyan}[3] ${NC}↝ Configure WARP"
echo -e "${red}[4] ${NC}↝ Uninstall WARP" echo -e "${red}[4] ${NC}↝ Uninstall WARP"
echo -e "${green}[5] ${NC}↝ Telegram Bot" echo -e "${green}[5] ${NC}↝ Telegram Bot"
echo -e "${green}[6] ${NC}↝ SingBox SubLink" echo -e "${green}[6] ${NC}↝ SingBox SubLink(${red}Deprecated${NC})"
echo -e "${green}[7] ${NC}↝ Normal-SUB SubLink" echo -e "${green}[7] ${NC}↝ Normal-SUB SubLink"
echo -e "${green}[8] ${NC}↝ Web Panel" echo -e "${green}[8] ${NC}↝ Web Panel"
echo -e "${cyan}[9] ${NC}↝ Change Port Hysteria2" echo -e "${cyan}[9] ${NC}↝ Change Port Hysteria2"

View File

@ -117,6 +117,23 @@ else
echo "$NORMALSUB_ENV not found. Skipping SUBPATH check." echo "$NORMALSUB_ENV not found. Skipping SUBPATH check."
fi fi
CONFIG_FILE="/etc/hysteria/config.json"
if [ -f "$CONFIG_FILE" ]; then
echo "Checking and converting pinSHA256 format in config.json"
if grep -q "pinSHA256.*=" "$CONFIG_FILE"; then
echo "Converting pinSHA256 from base64 to hex format"
HEX_FINGERPRINT=$(openssl x509 -noout -fingerprint -sha256 -inform pem -in /etc/hysteria/ca.crt | sed 's/.*=//;s///g')
sed -i "s|\"pinSHA256\": \"sha256/.*\"|\"pinSHA256\": \"$HEX_FINGERPRINT\"|" "$CONFIG_FILE"
echo "pinSHA256 converted to hex format: $HEX_FINGERPRINT"
else
echo "pinSHA256 appears to already be in hex format or not present, no conversion needed"
fi
fi
echo "Setting ownership and permissions" echo "Setting ownership and permissions"
chown hysteria:hysteria /etc/hysteria/ca.key /etc/hysteria/ca.crt chown hysteria:hysteria /etc/hysteria/ca.key /etc/hysteria/ca.crt
chmod 640 /etc/hysteria/ca.key /etc/hysteria/ca.crt chmod 640 /etc/hysteria/ca.key /etc/hysteria/ca.crt