diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 38ee449f..8ad585a4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -83,7 +83,7 @@ jobs: cd x-ui/bin # Download dependencies - Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v24.10.16/" + Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v24.10.31/" if [ "${{ matrix.platform }}" == "amd64" ]; then wget ${Xray_URL}Xray-linux-64.zip unzip Xray-linux-64.zip diff --git a/DockerInit.sh b/DockerInit.sh index b85acf0f..88f1da61 100755 --- a/DockerInit.sh +++ b/DockerInit.sh @@ -27,7 +27,7 @@ case $1 in esac mkdir -p build/bin cd build/bin -wget "https://github.com/XTLS/Xray-core/releases/download/v24.10.16/Xray-linux-${ARCH}.zip" +wget "https://github.com/XTLS/Xray-core/releases/download/v24.10.31/Xray-linux-${ARCH}.zip" unzip "Xray-linux-${ARCH}.zip" rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat mv xray "xray-linux-${FNAME}" diff --git a/config/version b/config/version index 26f8b8bc..62e64205 100644 --- a/config/version +++ b/config/version @@ -1 +1 @@ -2.4.5 \ No newline at end of file +2.4.6 \ No newline at end of file diff --git a/go.mod b/go.mod index 453311be..1a5c32ba 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 github.com/shirou/gopsutil/v4 v4.24.9 github.com/valyala/fasthttp v1.57.0 - github.com/xtls/xray-core v1.8.25-0.20241027003920-cf182b0482a4 + github.com/xtls/xray-core v1.8.25-0.20241031075831-4ec5c78c3453 go.uber.org/atomic v1.11.0 golang.org/x/text v0.19.0 google.golang.org/grpc v1.67.1 diff --git a/go.sum b/go.sum index edf78ab2..ea99f6dd 100644 --- a/go.sum +++ b/go.sum @@ -182,8 +182,8 @@ github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1Y github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463 h1:g1Cj7d+my6k/HHxLAyxPwyX8i7FGRr6ulBDMkBzg2BM= github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463/go.mod h1:BjIOLmkEEtAgloAiVUcYj0Mt+YU00JARZw8AEU0IwAg= -github.com/xtls/xray-core v1.8.25-0.20241027003920-cf182b0482a4 h1:5BMzz1alIs8js5ulsNueLv4zKKEdimFow907lyCsnSE= -github.com/xtls/xray-core v1.8.25-0.20241027003920-cf182b0482a4/go.mod h1:OlJhs59caMUabGbOamwTc2khBSOfd34qtVJVXFhpfWM= +github.com/xtls/xray-core v1.8.25-0.20241031075831-4ec5c78c3453 h1:2piT7IYX0SKhYjD+XiJMDZAbY01MkP1HYO54njmisaQ= +github.com/xtls/xray-core v1.8.25-0.20241031075831-4ec5c78c3453/go.mod h1:OlJhs59caMUabGbOamwTc2khBSOfd34qtVJVXFhpfWM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= diff --git a/main.go b/main.go index 25c5154c..0707d2d9 100644 --- a/main.go +++ b/main.go @@ -163,6 +163,15 @@ func showSetting(show bool) { fmt.Println("get webBasePath failed, error info(获取访问路径失败,错误信息):", err) } + certFile, err := settingService.GetCertFile() + if err != nil { + fmt.Println("get cert file failed, error info:", err) + } + keyFile, err := settingService.GetKeyFile() + if err != nil { + fmt.Println("get key file failed, error info:", err) + } + userService := service.UserService{} userModel, err := userService.GetFirstUser() if err != nil { @@ -284,7 +293,7 @@ func updateTgbotSetting(tgBotToken string, tgBotChatid string, tgBotRuntime stri } } -func updateSetting(port int, username string, password string, webBasePath string) { +func updateSetting(port int, username string, password string, webBasePath string, listenIP string) { err := database.InitDB(config.GetDBPath()) if err != nil { fmt.Println("Database initialization failed(初始化数据库失败):", err) @@ -320,6 +329,15 @@ func updateSetting(port int, username string, password string, webBasePath strin fmt.Println("Base URI path set successfully------>>设置访问路径成功") } } + + if listenIP != "" { + err := settingService.SetListen(listenIP) + if err != nil { + fmt.Println("Failed to set listen IP:", err) + } else { + fmt.Printf("listen %v set successfully", listenIP) + } + } } func updateCert(publicKey string, privateKey string) { @@ -349,6 +367,37 @@ func updateCert(publicKey string, privateKey string) { } } +func GetCertificate(getCert bool) { + if getCert { + settingService := service.SettingService{} + certFile, err := settingService.GetCertFile() + if err != nil { + fmt.Println("get cert file failed, error info:", err) + } + keyFile, err := settingService.GetKeyFile() + if err != nil { + fmt.Println("get key file failed, error info:", err) + } + + fmt.Println("cert:", certFile) + fmt.Println("key:", keyFile) + } +} + +func GetListenIP(getListen bool) { + if getListen { + + settingService := service.SettingService{} + ListenIP, err := settingService.GetListen() + if err != nil { + log.Printf("Failed to retrieve listen IP: %v", err) + return + } + + fmt.Println("listenIP:", ListenIP) + } +} + func migrateDb() { inboundService := service.InboundService{} @@ -408,6 +457,8 @@ func main() { var username string var password string var webBasePath string + var listenIP string + var getListen bool var webCertFile string var webKeyFile string var tgbottoken string @@ -416,6 +467,7 @@ func main() { var tgbotRuntime string var reset bool var show bool + var getCert bool var remove_secret bool settingCmd.BoolVar(&reset, "reset", false, "Reset all settings") settingCmd.BoolVar(&show, "show", false, "Display current settings") @@ -424,6 +476,9 @@ func main() { settingCmd.StringVar(&username, "username", "", "Set login username") settingCmd.StringVar(&password, "password", "", "Set login password") settingCmd.StringVar(&webBasePath, "webBasePath", "", "Set base path for Panel") + settingCmd.StringVar(&listenIP, "listenIP", "", "set panel listenIP IP") + settingCmd.BoolVar(&getListen, "getListen", false, "Display current panel listenIP IP") + settingCmd.BoolVar(&getCert, "getCert", false, "Display current certificate settings") settingCmd.StringVar(&webCertFile, "webCert", "", "Set path to public key file for panel") settingCmd.StringVar(&webKeyFile, "webCertKey", "", "Set path to private key file for panel") settingCmd.StringVar(&tgbottoken, "tgbottoken", "", "Set token for Telegram bot") @@ -466,11 +521,17 @@ func main() { if reset { resetSetting() } else { - updateSetting(port, username, password, webBasePath) + updateSetting(port, username, password, webBasePath, listenIP) } if show { showSetting(show) } + if getListen { + GetListenIP(getListen) + } + if getCert { + GetCertificate(getCert) + } if (tgbottoken != "") || (tgbotchatid != "") || (tgbotRuntime != "") { updateTgbotSetting(tgbottoken, tgbotchatid, tgbotRuntime) } @@ -491,7 +552,6 @@ func main() { } else { updateCert(webCertFile, webKeyFile) } - default: fmt.Println("Invalid subcommands----->>无效命令") fmt.Println() diff --git a/web/service/setting.go b/web/service/setting.go index 63b276bd..f6b9087b 100644 --- a/web/service/setting.go +++ b/web/service/setting.go @@ -243,6 +243,10 @@ func (s *SettingService) GetListen() (string, error) { return s.getString("webListen") } +func (s *SettingService) SetListen(ip string) error { + return s.setString("webListen", ip) +} + func (s *SettingService) GetWebDomain() (string, error) { return s.getString("webDomain") } diff --git a/x-ui.sh b/x-ui.sh index 1c089d36..8086e453 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -216,7 +216,6 @@ update_menu() { custom_version() { echo "输入面板版本 (例: 2.3.8):" read panel_version - if [ -z "$panel_version" ]; then echo "面板版本不能为空。" exit 1 @@ -225,7 +224,7 @@ custom_version() { download_link="https://raw.githubusercontent.com/xeefei/3x-ui/master/install.sh" # Use the entered panel version in the download link - install_command="bash <(curl -Ls $download_link) v$tag_version" + install_command="bash <(curl -Ls "https://raw.githubusercontent.com/mhsanaei/3x-ui/v$tag_version/install.sh") v$tag_version" echo "下载并安装面板版本 $panel_version..." eval $install_command @@ -1510,6 +1509,85 @@ remove_iplimit() { esac } +SSH_port_forwarding() { + local server_ip=$(curl -s https://api.ipify.org) + local existing_webBasePath=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'webBasePath: .+' | awk '{print $2}') + local existing_port=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'port: .+' | awk '{print $2}') + local existing_listenIP=$(/usr/local/x-ui/x-ui setting -getListen true | grep -Eo 'listenIP: .+' | awk '{print $2}') + local existing_cert=$(/usr/local/x-ui/x-ui setting -getCert true | grep -Eo 'cert: .+' | awk '{print $2}') + local existing_key=$(/usr/local/x-ui/x-ui setting -getCert true | grep -Eo 'key: .+' | awk '{print $2}') + + local config_listenIP="" + local listen_choice="" + + if [[ -n "$existing_cert" && -n "$existing_key" ]]; then + echo -e "${green}Panel is secure with SSL.${plain}" + return 0 + fi + if [[ -z "$existing_cert" && -z "$existing_key" && -z "$existing_listenIP" ]]; then + echo -e "\n${red}Warning: No Cert and Key found! The panel is not secure.${plain}" + echo "Please obtain a certificate or set up SSH port forwarding." + fi + + if [[ -n "$existing_listenIP" && (-z "$existing_cert" && -z "$existing_key") ]]; then + echo -e "\n${green}Current SSH Port Forwarding Configuration:${plain}" + echo -e "Standard SSH command:" + echo -e "${yellow}ssh -L 2222:${existing_listenIP}:${existing_port} root@${server_ip}${plain}" + echo -e "\nIf using SSH key:" + echo -e "${yellow}ssh -i -L 2222:${existing_listenIP}:${existing_port} root@${server_ip}${plain}" + echo -e "\nAfter connecting, access the panel at:" + echo -e "${yellow}http://localhost:2222${existing_webBasePath}${plain}" + fi + + echo -e "\nChoose an option:" + echo -e "${green}1.${plain} Set listen IP" + echo -e "${green}2.${plain} Clear listen IP" + echo -e "${green}0.${plain} Abort" + read -p "Choose an option: " num + + case "$num" in + 1) + if [[ -z "$existing_listenIP" ]]; then + echo -e "\nNo listenIP configured. Choose an option:" + echo -e "1. Use default IP (127.0.0.1)" + echo -e "2. Set a custom IP" + read -p "Select an option (1 or 2): " listen_choice + + config_listenIP="127.0.0.1" + [[ "$listen_choice" == "2" ]] && read -p "Enter custom IP to listen on: " config_listenIP + + /usr/local/x-ui/x-ui setting -listenIP "${config_listenIP}" >/dev/null 2>&1 + echo -e "${green}listen IP has been set to ${config_listenIP}.${plain}" + restart + else + config_listenIP="${existing_listenIP}" + echo -e "${green}Current listen IP is already set to ${config_listenIP}.${plain}" + fi + + if [[ -n "${config_listenIP}" ]]; then + echo -e "\n${green}SSH Port Forwarding Configuration:${plain}" + echo -e "Standard SSH command:" + echo -e "${yellow}ssh -L 2222:${config_listenIP}:${existing_port} root@${server_ip}${plain}" + echo -e "\nIf using SSH key:" + echo -e "${yellow}ssh -i -L 2222:${config_listenIP}:${existing_port} root@${server_ip}${plain}" + echo -e "\nAfter connecting, access the panel at:" + echo -e "${yellow}http://localhost:2222${existing_webBasePath}${plain}" + fi + ;; + 2) + /usr/local/x-ui/x-ui setting -listenIP ' ' >/dev/null 2>&1 + echo -e "${green}Listen IP has been cleared.${plain}" + restart + ;; + 0) + echo "Operation aborted." + ;; + *) + echo "Invalid option. Exiting." + ;; + esac +} + show_usage() { echo -e " ---------------------" echo -e " |${green}3X-UI 控制菜单用法 ${plain}|${plain}" @@ -1598,7 +1676,7 @@ show_menu() { check_install && update_menu ;; 4) - check_install && custom_version + check_install && legacy_version ;; 5) check_install && uninstall @@ -1652,12 +1730,15 @@ show_menu() { firewall_menu ;; 22) - bbr_menu + SSH_port_forwarding ;; 23) - update_geo + bbr_menu ;; 24) + update_geo + ;; + 25) run_speedtest ;; 25) @@ -1701,8 +1782,8 @@ if [[ $# > 0 ]]; then "update") check_install 0 && update 0 ;; - "custom") - check_install 0 && custom_version 0 + "legacy") + check_install 0 && legacy_version 0 ;; "install") check_uninstall 0 && install 0