diff --git a/README.md b/README.md index 3be3107..96c3f48 100644 --- a/README.md +++ b/README.md @@ -2,132 +2,189 @@
-اول اینکه این متد قرار نیست کانفیگ شما را زنده کند و دسترسی کامل به اینترنت را فراهم کند بلکه باعث میشود برخی سرویسهای خاص به طور مستقیم (بدون نیاز به سرور و یا حتی ورکر) در دسترس قرار گیرند +اول اینکه این متد قرار نیست کانفیگ شما را زنده کند و دسترسی کامل به اینترنت را +فراهم کند بلکه باعث میشود برخی سرویسهای خاص به طور مستقیم (بدون نیاز به سرور و +یا حتی ورکر) در دسترس قرار گیرند -در حال حاضر (۱۴۰۵/۳/۱۰) اجرای این متد امکان دسترسی به یوتویوب، اینستاگرام، واتس‌آپ، فیسبوک، رددیت و بعضی سایتهای پشت فستلی را فراهم میکند. +در حال حاضر (۱۴۰۵/۳/۱۰) اجرای این متد امکان دسترسی به یوتویوب، اینستاگرام، +واتس‌آپ، فیسبوک، رددیت و بعضی سایتهای پشت فستلی را فراهم میکند. -به محض اینکه هر سرویس دیگری با این متد در دسترس باشد اپدیت لازم را انجام خواهم داد. +به محض اینکه هر سرویس دیگری با این متد در دسترس باشد اپدیت لازم را انجام خواهم +داد. این متد بر روی ویندوز، لینوکس، مک و اندروید (بدون نیاز به روت) قابل اجراست. /// -این پروژه را ابتدا من در -[اینجا](https://github.com/patterniha/MMDF) -نوشتم و سپس با تلاشهای انجام شده در -[اینجا](https://github.com/XTLS/Xray-core/issues/4348) -به Xray-core اضافه کردیم و یعنی اکنون میتوانید با یک کانفیگ ساده‌ی v2ray از این متد استفاده کنید. +این پروژه را ابتدا من در [اینجا](https://github.com/patterniha/MMDF) نوشتم و سپس +با تلاشهای انجام شده در [اینجا](https://github.com/XTLS/Xray-core/issues/4348) به +Xray-core اضافه کردیم و یعنی اکنون میتوانید با یک کانفیگ ساده‌ی v2ray از این متد +استفاده کنید. -نحوه کارکرد متد همانطور که از اسمش پیداست ابتدا هویت سرور اصلی را جعل میکند تا دیتای غیر رمز شده را از مرورگر دریافت کند سپس با یک sni جعلی آن را به سرور اصلی میفرستد. +نحوه کارکرد متد همانطور که از اسمش پیداست ابتدا هویت سرور اصلی را جعل میکند تا +دیتای غیر رمز شده را از مرورگر دریافت کند سپس با یک sni جعلی آن را به سرور اصلی +میفرستد. -تنظیم اولیه متد مراحل کمی طولانی دارد ولی بعد از انجام تنظیمات صرفا یک روشن/خاموش ساده برای فعال/غیرفعال کردن متد لازم است. +تنظیم اولیه متد مراحل کمی طولانی دارد ولی بعد از انجام تنظیمات صرفا یک روشن/خاموش +ساده برای فعال/غیرفعال کردن متد لازم است. ## راه اندازی در ویندوز -۱. ابتدا آخرین ورژن برنامه -v2rayN (v2rayN-windows-64.zip -) -را از -https://github.com/2dust/v2rayN/releases -دانلود و اکسترکت کنید +۱. ابتدا آخرین ورژن برنامه v2rayN (v2rayN-windows-64.zip ) را از +https://github.com/2dust/v2rayN/releases دانلود و اکسترکت کنید -۲. حال نیاز به یک سرتیفیکیت شخصی دارید برای این کار فایل -certificate_generator.bat -را به فولدر -v2rayN-windows-64\bin -منتقل و در همانجا اجرا کنید -کمی صبر کنید سپس دو فایل -mycert.crt -و -mycert.key -ایجاد میشود +۲. حال نیاز به یک سرتیفیکیت شخصی دارید برای این کار فایل +certificate_generator.bat را به فولدر v2rayN-windows-64\bin منتقل و در همانجا +اجرا کنید کمی صبر کنید سپس دو فایل mycert.crt و mycert.key ایجاد میشود -**هشدار: حتما از سرتیفیکیت شخصی خود استفاده کنید و به هیچ عنوان از سرتیفیکیت (crt) دیگران استفاده نکنید و همچنین فایل پرایویت‌کی (key) خود را به هیچ شخصی ندهید** +**هشدار: حتما از سرتیفیکیت شخصی خود استفاده کنید و به هیچ عنوان از سرتیفیکیت +(crt) دیگران استفاده نکنید و همچنین فایل پرایویت‌کی (key) خود را به هیچ شخصی +ندهید** -۳. حال باید سرتیفیکیت (crt) ایجاد شده را به عنوان trusted root certificate به سیستم عامل (برای تایید روی کل سیستم) و یا یک مرورگر خاص خود معرفی کنید +۳. حال باید سرتیفیکیت (crt) ایجاد شده را به عنوان trusted root certificate به +سیستم عامل (برای تایید روی کل سیستم) و یا یک مرورگر خاص خود معرفی کنید -برای معرفی به سیستم عامل باید روی mycert.crt راست کلیک کنید و install certificate را انتخاب کنید سپس گزینه local machine را انتخاب کنید در صفحه بعد -place all certificates in the following store -را انتخاب و +برای معرفی به سیستم عامل باید روی mycert.crt راست کلیک کنید و install +certificate را انتخاب کنید سپس گزینه local machine را انتخاب کنید در صفحه بعد +place all certificates in the following store را انتخاب و -فولدر -Trusted Root Certification Authorities -را انتخاب کنید و تایید کنید +فولدر Trusted Root Certification Authorities را انتخاب کنید و تایید کنید برای مرورگر نیز به طور مثال کروم باید مراحل زیر را طی کنید -Settings -> Privacy and security -> Security -> Manage certificates -> Manage imported certificates from Windows -> Trusted Root Certification Authorities -> Import -> Select mycert.crt file -> Place all certificates in the following store -> Select "Trusted Root Certification Authorities" +Settings -> Privacy and security -> Security -> Manage certificates -> Manage +imported certificates from Windows -> Trusted Root Certification Authorities -> +Import -> Select mycert.crt file -> Place all certificates in the following +store -> Select "Trusted Root Certification Authorities" -۴. نرم افزار v2rayN را اجرا کنید و از قسمت configuration بر روی -add a custom configuration -کلیک کنید حال یک نام دلخواه انتخاب کنید و فایل کانفیگ -MITM-DomainFronting.json -را وارد کنید -core type -را بر روی xray و socks port را حتما خالی بزارید +۴. نرم افزار v2rayN را اجرا کنید و از قسمت configuration بر روی add a custom +configuration کلیک کنید حال یک نام دلخواه انتخاب کنید و فایل کانفیگ +MITM-DomainFronting.json را وارد کنید core type را بر روی xray و socks port را +حتما خالی بزارید -۵. کانفیگ را انتخاب کرده و set system proxy را انتخاب کنید - کار تمام است اکنون میتوانید بر روی مرورگری که سرتیفیکیت را در آن وارد کردید (و یا کل سیستم در صورتی که سرتیفیکیت را به سیستم عامل معرفی کردید) -از این متد استفاده کنید. +۵. کانفیگ را انتخاب کرده و set system proxy را انتخاب کنید کار تمام است اکنون +میتوانید بر روی مرورگری که سرتیفیکیت را در آن وارد کردید (و یا کل سیستم در صورتی +که سرتیفیکیت را به سیستم عامل معرفی کردید) از این متد استفاده کنید. ## راه اندازی در اندروید -۱. ابتدا آخرین ورژن برنامه v2rayNG را از -https://github.com/2dust/v2rayNG/releases -دانلود و نصب کنید +۱. ابتدا آخرین ورژن برنامه v2rayNG را از +https://github.com/2dust/v2rayNG/releases دانلود و نصب کنید -۲. حال نیاز به یک سرتیفیکیت شخصی دارید برای اینکار میتوانید همان فایلهای -mycert.crt, mycert.key -را که در ویندوز ایجاد کردید را به گوشی خود منتقل کنید و از همانها استفاده کنید -یا اینکه به طور مثال میتوانید به طور مستقیم از سایت +۲. حال نیاز به یک سرتیفیکیت شخصی دارید برای اینکار میتوانید همان فایلهای +mycert.crt, mycert.key را که در ویندوز ایجاد کردید را به گوشی خود منتقل کنید و +از همانها استفاده کنید یا اینکه به طور مثال میتوانید به طور مستقیم از سایت https://regery.com/en/security/ssl-tools/self-signed-certificate-generator -با یک نام دلخواه سرتیفیکیت بسازید و هر دو فایل crt و key را دانلود کنید -در این صورت باید نام فایل crt را به mycert.crt و نام فایل key را به mycert.key تغییر دهید +با یک نام دلخواه سرتیفیکیت بسازید و هر دو فایل crt و key را دانلود کنید در این +صورت باید نام فایل crt را به mycert.crt و نام فایل key را به mycert.key تغییر +دهید -**هشدار: حتما از سرتیفیکیت شخصی خود استفاده کنید و به هیچ عنوان از سرتیفیکیت (crt) دیگران استفاده نکنید و همچنین فایل پرایویت‌کی (key) خود را به هیچ شخصی ندهید** +**هشدار: حتما از سرتیفیکیت شخصی خود استفاده کنید و به هیچ عنوان از سرتیفیکیت +(crt) دیگران استفاده نکنید و همچنین فایل پرایویت‌کی (key) خود را به هیچ شخصی +ندهید** -۳. در برنامه v2rayNG و در قسمت Asset files هر دو فایل -mycert.crt, mycert.key -را وارد کنید +۳. در برنامه v2rayNG و در قسمت Asset files هر دو فایل mycert.crt, mycert.key را +وارد کنید -۴. حال باید سرتیفیکیت (crt) را به عنوان یک trusted root certificate به سیستم عامل اندروید معرفی کنید برای این کار مراحل زیر را طی کنید: +۴. حال باید سرتیفیکیت (crt) را به عنوان یک trusted root certificate به سیستم +عامل اندروید معرفی کنید برای این کار مراحل زیر را طی کنید: -Setting -> Security and privacy -> More security settings -> Install from device storage -> CA Certificate -> Install anyway -> Select mycert.crt file on your storage. +Setting -> Security and privacy -> More security settings -> Install from device +storage -> CA Certificate -> Install anyway -> Select mycert.crt file on your +storage. اگر با موفقیت این قسمت انجام شود میتوانید سرتیفیکیت وارد شده را در قسمت -Setting -> Security and privacy -> More security settings -> View security certificates -> User. +Setting -> Security and privacy -> More security settings -> View security +certificates -> User. -مشاهده کنید، دقت کنید که این مراحل ممکن است بر روی گوشی های مختلف کمی متفاوت باشد +مشاهده کنید، دقت کنید که این مراحل ممکن است بر روی گوشی های مختلف کمی متفاوت +باشد -۵. کانفیگ -MITM-DomainFronting.json -را از طریق -import from locally -وارد برنامهv2rayNG کنید و اجرا کنید -همچنین دقت کنید که Enable Hev TUN FEATURE در تنظیمات v2rayNG فعال باشد و همچنین پورت پیشفرض 10808 را تغییر نداده باشید. +۵. کانفیگ MITM-DomainFronting.json را از طریق import from locally وارد +برنامهv2rayNG کنید و اجرا کنید همچنین دقت کنید که Enable Hev TUN FEATURE در +تنظیمات v2rayNG فعال باشد و همچنین پورت پیشفرض 10808 را تغییر نداده باشید. -۶. کار تمام است اکنون میتوانید بر روی مرورگر کروم (و به طور کلی تمامی مرورگرهای مبتنی بر کرومیوم) از این متد استفاده کنید +۶. کار تمام است اکنون میتوانید بر روی مرورگر کروم (و به طور کلی تمامی مرورگرهای +مبتنی بر کرومیوم) از این متد استفاده کنید و در صورتی که از مرورگر فایرفاکس استفاده میکنید باید مراحل اضافه زیر را طی کنید -firefox browser -> Settings -> About Firefox -> Tap the Firefox logo five times -> Navigate to Settings -> Secret Settings -> Toggle "Use third party CA certificates" +firefox browser -> Settings -> About Firefox -> Tap the Firefox logo five times +-> Navigate to Settings -> Secret Settings -> Toggle "Use third party CA +certificates" -دقت کنید برای اندروید غیر روت فقط از طریق مرورگرها میتوانید ازین متد استفاده کنید و برنامه های مستقل امکان استفاده از این متد را معمولا ندارند. +دقت کنید برای اندروید غیر روت فقط از طریق مرورگرها میتوانید ازین متد استفاده +کنید و برنامه های مستقل امکان استفاده از این متد را معمولا ندارند. +## راه اندازی در لینوکس + +۱. ابتدا اسکریپت تنظیم را اجرا کنید: + +```bash +chmod +x Xray-config/linux-key-generator.sh && ./Xray-config/linux-key-generator.sh +``` + +گزینه ۳ (Do both) را انتخاب کنید تا هم سرتیفیکیت ایجاد شود و هم Xray دانلود شود. + +۲. حال باید سرتیفیکیت ایجاد شده (`Xray-config/mycert.crt`) را به عنوان trusted +root certificate به سیستم عامل معرفی کنید: + +**برای اوبونتو/دبیان:** + +```bash +sudo cp Xray-config/mycert.crt /usr/local/share/ca-certificates/mycert.crt +sudo update-ca-certificates +``` + +**برای فدورا/ردهت:** + +```bash +sudo cp Xray-config/mycert.crt /etc/pki/ca-trust/source/anchors/mycert.crt +sudo update-ca-trust +``` + +۳. اگر از فایرفاکس استفاده میکنید باید سرتیفیکیت را به مرورگر نیز معرفی کنید: + +Firefox Settings -> Privacy & Security -> Certificates -> View Certificates -> +تب Authorities -> Import -> فایل `Xray-config/mycert.crt` را انتخاب کنید -> +گزینه Trust to identify websites را فعال کنید + +۴. Xray را با کانفیگ MITM Domain Fronting اجرا کنید: + +```bash +chmod +x ./Xray/xray && ./Xray/xray run -c ./Xray-config/MITM-DomainFronting.json +``` + +۵. مرورگر خود را برای استفاده از پروکسی تنظیم کنید: + +- آدرس پروکسی: 127.0.0.1 +- پورت: 10808 +- نوع: SOCKS5 + +۶. کار تمام است! اکنون میتوانید در مرورگر فایرفاکس از این متد استفاده کنید (برای +کروم بهتر است از اکستنشن proxy switcher استفاده کنید). + +**نکته:** در لینوکس نیز مانند اندروید، فقط از طریق مرورگرها میتوانید از این متد +استفاده کنید و برنامه های مستقل معمولا پشتیبانی نمیکنند. # هشدار ها و نکات -۱. **باز هم تاکید میکنم فایل سرتیفیکیت (crt) را از کسی نگیرید و فایل پرایویت‌کی (key) را به هیچ شخصی ندهید به طور ساده این دو فایل را نه به کسی بدهید و نه از کسی بگیرید و خودتان به صورت شخصی ایجاد و از آن استفاده کنید** +۱. **باز هم تاکید میکنم فایل سرتیفیکیت (crt) را از کسی نگیرید و فایل پرایویت‌کی +(key) را به هیچ شخصی ندهید به طور ساده این دو فایل را نه به کسی بدهید و نه از +کسی بگیرید و خودتان به صورت شخصی ایجاد و از آن استفاده کنید** +۲. برای اندروید غیر روت ازین متد فقط میتوانید بر روی مرورگرها استفاده کنید و اپ +های مستقل معمولا از این متد پشتیبانی نمیکنند -۲. برای اندروید غیر روت ازین متد فقط میتوانید بر روی مرورگرها استفاده کنید و اپ های مستقل معمولا از این متد پشتیبانی نمیکنند +بنابراین برای استفاده از google meet و یا google drive و ... باید از مرورگر +استفاده کنید. - بنابراین برای استفاده از google meet و یا google drive و ... باید از مرورگر استفاده کنید. - -۳. زحمت زیادی برای برای این برنامه کشیده شده از نوشتن کد پایتون اولیه تا اضافه کردن آن به هسته xray امیدوارم حمایت از بنده فراموش نشه همچنان کارهای بزرگی در پیش هست ... +۳. زحمت زیادی برای برای این برنامه کشیده شده از نوشتن کد پایتون اولیه تا اضافه +کردن آن به هسته xray امیدوارم حمایت از بنده فراموش نشه همچنان کارهای بزرگی در +پیش هست ...
diff --git a/Xray-config/MITM-DomainFronting.json b/Xray-config/MITM-DomainFronting.json index ea9749f..1a80c28 100644 --- a/Xray-config/MITM-DomainFronting.json +++ b/Xray-config/MITM-DomainFronting.json @@ -96,8 +96,8 @@ "certificates": [ { "usage": "issue", - "certificateFile": "mycert.crt", - "keyFile": "mycert.key" + "certificateFile": "../Xray-config/mycert.crt", + "keyFile": "../Xray-config/mycert.key" } ] } @@ -119,8 +119,8 @@ "certificates": [ { "usage": "issue", - "certificateFile": "mycert.crt", - "keyFile": "mycert.key" + "certificateFile": "../Xray-config/mycert.crt", + "keyFile": "../Xray-config/mycert.key" } ] } diff --git a/Xray-config/linux-key-generator.sh b/Xray-config/linux-key-generator.sh new file mode 100755 index 0000000..f0829d7 --- /dev/null +++ b/Xray-config/linux-key-generator.sh @@ -0,0 +1,264 @@ +#!/bin/bash + +# --- Combined script: Generate certificate & download Xray-core --- +# Fixed to handle proxy and SSL certificate issues + +print_status() { + echo -e "\e[1;34m[INFO]\e[0m $1" +} + +print_success() { + echo -e "\e[1;32m[SUCCESS]\e[0m $1" +} + +print_error() { + echo -e "\e[1;31m[ERROR]\e[0m $1" >&2 +} + +print_warning() { + echo -e "\e[1;33m[WARNING]\e[0m $1" +} + +# Function to check if a file is a valid ZIP +is_valid_zip() { + if [ -f "$1" ] && unzip -t "$1" &> /dev/null; then + return 0 + else + return 1 + fi +} + +# Function to generate self-signed certificate +generate_certificate() { + print_status "Generating self-signed certificate..." + + if ! command -v openssl &> /dev/null; then + print_error "OpenSSL not installed. Skipping certificate generation." + return 1 + fi + + local script_dir=$(dirname "$0") + local cert_path="$script_dir/mycert.crt" + local key_path="$script_dir/mycert.key" + + # Check if files already exist + if [ -f "$cert_path" ] || [ -f "$key_path" ]; then + print_warning "Certificate files already exist." + read -p "Overwrite? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_status "Skipping certificate generation." + return 0 + fi + fi + + openssl req -x509 -newkey rsa:2048 -nodes \ + -keyout "$key_path" -out "$cert_path" \ + -days 365 -subj "/C=US/ST=State/L=City/O=Org/CN=localhost" 2>/dev/null + + if [ $? -eq 0 ] && [ -f "$cert_path" ] && [ -f "$key_path" ]; then + chmod 600 "$key_path" + print_success "Certificate generated: $cert_path and $key_path" + ls -lh "$cert_path" "$key_path" + else + print_error "Certificate generation failed" + return 1 + fi +} + +# Function to download Xray-core with proxy handling +download_xray() { + print_status "Downloading Xray-core..." + + URL="https://github.com/XTLS/Xray-core/releases/download/v26.6.1/Xray-linux-64.zip" + ZIP="Xray-linux-64.zip" + DIR="./Xray" + + # Check if ZIP already exists and is valid + if [ -f "$ZIP" ] && is_valid_zip "$ZIP"; then + print_status "Valid ZIP file already exists: $ZIP" + read -p "Use existing file? (Y/n): " -n 1 -r + echo + if [[ $REPLY =~ ^[Nn]$ ]]; then + rm -f "$ZIP" + else + print_status "Using existing ZIP file." + extract_xray "$ZIP" "$DIR" + return $? + fi + elif [ -f "$ZIP" ]; then + print_warning "Existing ZIP file is corrupt. Re-downloading..." + rm -f "$ZIP" + fi + + # Create directory + mkdir -p "$DIR" + + # Detect if we're behind a proxy + if [ -n "$http_proxy" ] || [ -n "$https_proxy" ] || [ -n "$HTTP_PROXY" ] || [ -n "$HTTPS_PROXY" ]; then + print_warning "Proxy detected. Using --no-check-certificate to bypass SSL issues." + WGET_OPTS="--no-check-certificate" + CURL_OPTS="-k" + else + WGET_OPTS="" + CURL_OPTS="" + fi + + # Download with retry logic + local max_retries=3 + local retry_count=0 + local download_success=0 + + while [ $retry_count -lt $max_retries ] && [ $download_success -eq 0 ]; do + if [ $retry_count -gt 0 ]; then + print_status "Retry attempt $((retry_count+1))/$max_retries..." + sleep 2 + fi + + if command -v wget &> /dev/null; then + print_status "Using wget to download..." + wget $WGET_OPTS -O "$ZIP" "$URL" 2>&1 | grep -v "ERROR: cannot verify" + if [ $? -eq 0 ] && is_valid_zip "$ZIP"; then + download_success=1 + else + print_warning "Download attempt $((retry_count+1)) failed" + rm -f "$ZIP" + fi + elif command -v curl &> /dev/null; then + print_status "Using curl to download..." + curl -L $CURL_OPTS -o "$ZIP" "$URL" --progress-bar + if [ $? -eq 0 ] && is_valid_zip "$ZIP"; then + download_success=1 + else + print_warning "Download attempt $((retry_count+1)) failed" + rm -f "$ZIP" + fi + else + print_error "wget or curl required" + return 1 + fi + + retry_count=$((retry_count+1)) + done + + if [ $download_success -eq 0 ]; then + print_error "Failed to download Xray-core after $max_retries attempts." + print_status "Possible solutions:" + echo " 1. Check your internet connection" + echo " 2. Disable your proxy: unset http_proxy https_proxy" + echo " 3. Download manually and place in this directory" + return 1 + fi + + # Extract the ZIP + extract_xray "$ZIP" "$DIR" +} + +# Function to extract Xray +extract_xray() { + local zip_file="$1" + local extract_dir="$2" + + print_status "Extracting $zip_file to $extract_dir..." + + if ! is_valid_zip "$zip_file"; then + print_error "Invalid ZIP file: $zip_file" + return 1 + fi + + # Clear the directory first + if [ -d "$extract_dir" ] && [ "$(ls -A "$extract_dir" 2>/dev/null)" ]; then + print_warning "Directory $extract_dir is not empty." + read -p "Clear it before extraction? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + rm -rf "$extract_dir"/* + fi + fi + + if unzip -o "$zip_file" -d "$extract_dir" > /dev/null 2>&1; then + print_success "Successfully extracted to: $extract_dir" + + # Show what was extracted + echo "" + echo "Contents of $extract_dir:" + ls -la "$extract_dir" + + # Set executable permissions for binary files + print_status "Setting executable permissions..." + find "$extract_dir" -type f -executable -exec chmod +x {} \; + + # Clean up ZIP file + read -p "Delete the ZIP file? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + rm -f "$zip_file" + print_status "ZIP file removed." + fi + + print_success "Xray-core is ready in $extract_dir" + return 0 + else + print_error "Extraction failed!" + return 1 + fi +} + +# Function to manually download if automatic fails +manual_download_instructions() { + echo "" + print_warning "Automatic download failed. You can manually download:" + echo " 1. Visit: https://github.com/XTLS/Xray-core/releases" + echo " 2. Download: Xray-linux-64.zip" + echo " 3. Place it in: $(pwd)" + echo " 4. Run this script again" + echo "" + print_status "Or try disabling your proxy and re-running:" + echo " unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY" + echo " ./$(basename "$0")" +} + +# Main execution +main() { + echo "=== Xray Setup Script ===" + echo "1. Generate SSL Certificate" + echo "2. Download Xray-core" + echo "3. Do both" + echo "4. Exit" + echo "" + read -p "Select option (1/2/3/4): " -n 1 -r + echo + + case $REPLY in + 1) + generate_certificate + ;; + 2) + if ! download_xray; then + manual_download_instructions + exit 1 + fi + ;; + 3) + generate_certificate + echo "" + if ! download_xray; then + manual_download_instructions + exit 1 + fi + ;; + 4) + print_status "Exiting..." + exit 0 + ;; + *) + print_error "Invalid option" + exit 1 + ;; + esac + + print_success "Setup complete!" +} + +# Run the main function +main \ No newline at end of file