menu.sh 120 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879
  1. #!/bin/bash
  2. C_RESET=$'\033[0m'
  3. C_BOLD=$'\033[1m'
  4. C_DIM=$'\033[2m'
  5. C_UL=$'\033[4m'
  6. # Premium Color Palette
  7. C_RED=$'\033[38;5;196m' # Bright Red
  8. C_GREEN=$'\033[38;5;46m' # Neon Green
  9. C_YELLOW=$'\033[38;5;226m' # Bright Yellow
  10. C_BLUE=$'\033[38;5;39m' # Deep Sky Blue
  11. C_PURPLE=$'\033[38;5;135m' # Light Purple
  12. C_CYAN=$'\033[38;5;51m' # Cyan
  13. C_WHITE=$'\033[38;5;255m' # Bright White
  14. C_GRAY=$'\033[38;5;245m' # Gray
  15. C_ORANGE=$'\033[38;5;208m' # Orange
  16. # Semantic Aliases
  17. C_TITLE=$C_PURPLE
  18. C_CHOICE=$C_CYAN
  19. C_PROMPT=$C_BLUE
  20. C_WARN=$C_YELLOW
  21. C_DANGER=$C_RED
  22. C_STATUS_A=$C_GREEN
  23. C_STATUS_I=$C_GRAY
  24. C_ACCENT=$C_ORANGE
  25. DB_DIR="/etc/firewallfalcon"
  26. DB_FILE="$DB_DIR/users.db"
  27. INSTALL_FLAG_FILE="$DB_DIR/.install"
  28. BADVPN_SERVICE_FILE="/etc/systemd/system/badvpn.service"
  29. BADVPN_BUILD_DIR="/root/badvpn-build"
  30. HAPROXY_CONFIG="/etc/haproxy/haproxy.cfg"
  31. NGINX_CONFIG_FILE="/etc/nginx/sites-available/default"
  32. SSL_CERT_DIR="/etc/firewallfalcon/ssl"
  33. SSL_CERT_FILE="$SSL_CERT_DIR/firewallfalcon.pem"
  34. NGINX_PORTS_FILE="$DB_DIR/nginx_ports.conf"
  35. DNSTT_SERVICE_FILE="/etc/systemd/system/dnstt.service"
  36. DNSTT_BINARY="/usr/local/bin/dnstt-server"
  37. DNSTT_KEYS_DIR="/etc/firewallfalcon/dnstt"
  38. DNSTT_CONFIG_FILE="$DB_DIR/dnstt_info.conf"
  39. DNS_INFO_FILE="$DB_DIR/dns_info.conf"
  40. UDP_CUSTOM_DIR="/root/udp"
  41. UDP_CUSTOM_SERVICE_FILE="/etc/systemd/system/udp-custom.service"
  42. SSH_BANNER_FILE="/etc/bannerssh"
  43. FALCONPROXY_SERVICE_FILE="/etc/systemd/system/falconproxy.service"
  44. FALCONPROXY_BINARY="/usr/local/bin/falconproxy"
  45. FALCONPROXY_CONFIG_FILE="$DB_DIR/falconproxy_config.conf"
  46. LIMITER_SCRIPT="/usr/local/bin/firewallfalcon-limiter.sh"
  47. LIMITER_SERVICE="/etc/systemd/system/firewallfalcon-limiter.service"
  48. # --- ZiVPN Variables ---
  49. ZIVPN_DIR="/etc/zivpn"
  50. ZIVPN_BIN="/usr/local/bin/zivpn"
  51. ZIVPN_SERVICE_FILE="/etc/systemd/system/zivpn.service"
  52. ZIVPN_CONFIG_FILE="$ZIVPN_DIR/config.json"
  53. ZIVPN_CERT_FILE="$ZIVPN_DIR/zivpn.crt"
  54. ZIVPN_KEY_FILE="$ZIVPN_DIR/zivpn.key"
  55. DESEC_TOKEN="V55cFY8zTictLCPfviiuX5DHjs15"
  56. DESEC_DOMAIN="firewallfalcon.thefirewoods.org"
  57. SELECTED_USER=""
  58. UNINSTALL_MODE="interactive"
  59. if [[ $EUID -ne 0 ]]; then
  60. echo -e "${C_RED}❌ Error: This script requires root privileges to run.${C_RESET}"
  61. exit 1
  62. fi
  63. # Mandatory Dependency Check (Added jq and curl)
  64. check_environment() {
  65. # Mandatory Dependency Check (Added jq and curl)
  66. for cmd in bc jq curl wget; do
  67. if ! command -v $cmd &> /dev/null; then
  68. echo -e "${C_YELLOW}⚠️ Warning: '$cmd' not found. Installing...${C_RESET}"
  69. apt-get update > /dev/null 2>&1 && apt-get install -y $cmd || {
  70. echo -e "${C_RED}❌ Error: Failed to install '$cmd'. Please install it manually.${C_RESET}"
  71. exit 1
  72. }
  73. fi
  74. done
  75. }
  76. initial_setup() {
  77. echo -e "${C_BLUE}⚙️ Initializing FirewallFalcon Manager setup...${C_RESET}"
  78. check_environment
  79. mkdir -p "$DB_DIR"
  80. touch "$DB_FILE"
  81. mkdir -p "$SSL_CERT_DIR"
  82. echo -e "${C_BLUE}🔹 Configuring user limiter service...${C_RESET}"
  83. echo -e "${C_BLUE}🔹 Configuring user limiter service...${C_RESET}"
  84. setup_limiter_service
  85. if [ ! -f "$INSTALL_FLAG_FILE" ]; then
  86. touch "$INSTALL_FLAG_FILE"
  87. fi
  88. echo -e "${C_GREEN}✅ Setup finished.${C_RESET}"
  89. }
  90. _is_valid_ipv4() {
  91. local ip=$1
  92. if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
  93. return 0
  94. else
  95. return 1
  96. fi
  97. }
  98. check_and_open_firewall_port() {
  99. local port="$1"
  100. local protocol="${2:-tcp}"
  101. local firewall_detected=false
  102. if command -v ufw &> /dev/null && ufw status | grep -q "Status: active"; then
  103. firewall_detected=true
  104. if ! ufw status | grep -qw "$port/$protocol"; then
  105. echo -e "${C_YELLOW}🔥 UFW firewall is active and port ${port}/${protocol} is closed.${C_RESET}"
  106. read -p "👉 Do you want to open this port now? (y/n): " confirm
  107. if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
  108. ufw allow "$port/$protocol"
  109. echo -e "${C_GREEN}✅ Port ${port}/${protocol} has been opened in UFW.${C_RESET}"
  110. else
  111. echo -e "${C_RED}❌ Warning: Port ${port}/${protocol} was not opened. The service may not work correctly.${C_RESET}"
  112. return 1
  113. fi
  114. else
  115. echo -e "${C_GREEN}✅ Port ${port}/${protocol} is already open in UFW.${C_RESET}"
  116. fi
  117. fi
  118. if command -v firewall-cmd &> /dev/null && systemctl is-active --quiet firewalld; then
  119. firewall_detected=true
  120. if ! firewall-cmd --list-ports --permanent | grep -qw "$port/$protocol"; then
  121. echo -e "${C_YELLOW}🔥 firewalld is active and port ${port}/${protocol} is not open.${C_RESET}"
  122. read -p "👉 Do you want to open this port now? (y/n): " confirm
  123. if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
  124. firewall-cmd --add-port="$port/$protocol" --permanent
  125. firewall-cmd --reload
  126. echo -e "${C_GREEN}✅ Port ${port}/${protocol} has been opened in firewalld.${C_RESET}"
  127. else
  128. echo -e "${C_RED}❌ Warning: Port ${port}/${protocol} was not opened. The service may not work correctly.${C_RESET}"
  129. return 1
  130. fi
  131. else
  132. echo -e "${C_GREEN}✅ Port ${port}/${protocol} is already open in firewalld.${C_RESET}"
  133. fi
  134. fi
  135. if ! $firewall_detected; then
  136. echo -e "${C_BLUE}ℹ️ No active firewall (UFW or firewalld) detected. Assuming ports are open.${C_RESET}"
  137. fi
  138. return 0
  139. }
  140. check_and_free_ports() {
  141. local ports_to_check=("$@")
  142. for port in "${ports_to_check[@]}"; do
  143. echo -e "\n${C_BLUE}🔎 Checking if port $port is available...${C_RESET}"
  144. local conflicting_process_info
  145. conflicting_process_info=$(ss -lntp | grep ":$port\s" || ss -lunp | grep ":$port\s")
  146. if [[ -n "$conflicting_process_info" ]]; then
  147. local conflicting_pid
  148. conflicting_pid=$(echo "$conflicting_process_info" | grep -oP 'pid=\K[0-9]+' | head -n 1)
  149. local conflicting_name
  150. conflicting_name=$(echo "$conflicting_process_info" | grep -oP 'users:\(\("(\K[^"]+)' | head -n 1)
  151. echo -e "${C_YELLOW}⚠️ Warning: Port $port is in use by process '${conflicting_name:-unknown}' (PID: ${conflicting_pid:-N/A}).${C_RESET}"
  152. read -p "👉 Do you want to attempt to stop this process? (y/n): " kill_confirm
  153. if [[ "$kill_confirm" == "y" || "$kill_confirm" == "Y" ]]; then
  154. echo -e "${C_GREEN}🛑 Stopping process PID $conflicting_pid...${C_RESET}"
  155. systemctl stop "$(ps -p "$conflicting_pid" -o comm=)" &>/dev/null || kill -9 "$conflicting_pid"
  156. sleep 2
  157. if ss -lntp | grep -q ":$port\s" || ss -lunp | grep -q ":$port\s"; then
  158. echo -e "${C_RED}❌ Failed to free port $port. Please handle it manually. Aborting.${C_RESET}"
  159. return 1
  160. else
  161. echo -e "${C_GREEN}✅ Port $port has been successfully freed.${C_RESET}"
  162. fi
  163. else
  164. echo -e "${C_RED}❌ Cannot proceed without freeing port $port. Aborting.${C_RESET}"
  165. return 1
  166. fi
  167. else
  168. echo -e "${C_GREEN}✅ Port $port is free to use.${C_RESET}"
  169. fi
  170. done
  171. return 0
  172. }
  173. setup_limiter_service() {
  174. # Updated logic: No logging, smart 120s lockout
  175. cat > "$LIMITER_SCRIPT" << 'EOF'
  176. #!/bin/bash
  177. DB_FILE="/etc/firewallfalcon/users.db"
  178. # Loop continuously with optimized sleep
  179. while true; do
  180. if [[ ! -f "$DB_FILE" ]]; then
  181. sleep 30
  182. continue
  183. fi
  184. current_ts=$(date +%s)
  185. # Cache active users to minimize pgrep calls inside loop
  186. # Get count of sshd processes per user in one go is hard in bash without map,
  187. # so we optimize the per-user check.
  188. while IFS=: read -r user pass expiry limit; do
  189. [[ -z "$user" || "$user" == \#* ]] && continue
  190. # 1. Active Check (Skip if user has no processes to save CPU)
  191. # pgrep -u is relatively cheap, but let's be smart.
  192. # If connection limit is huge, we might not care.
  193. # --- Expiry Check ---
  194. # Only check expiry if we have a valid expiry date
  195. if [[ "$expiry" != "Never" && "$expiry" != "" ]]; then
  196. expiry_ts=$(date -d "$expiry" +%s 2>/dev/null || echo 0)
  197. if [[ $expiry_ts -lt $current_ts && $expiry_ts -ne 0 ]]; then
  198. if ! passwd -S "$user" | grep -q " L "; then
  199. usermod -L "$user" &>/dev/null
  200. killall -u "$user" -9 &>/dev/null
  201. fi
  202. continue
  203. fi
  204. fi
  205. # --- Connection Limit Check ---
  206. # Optimization: pgrep -c is faster than pipe to wc
  207. online_count=$(pgrep -c -u "$user" sshd)
  208. if ! [[ "$limit" =~ ^[0-9]+$ ]]; then limit=1; fi
  209. if [[ "$online_count" -gt "$limit" ]]; then
  210. if ! passwd -S "$user" | grep -q " L "; then
  211. usermod -L "$user" &>/dev/null
  212. killall -u "$user" -9 &>/dev/null
  213. (sleep 120; usermod -U "$user" &>/dev/null) &
  214. else
  215. killall -u "$user" -9 &>/dev/null
  216. fi
  217. fi
  218. done < "$DB_FILE"
  219. # Sleep increased to 25 seconds to reduce CPU load
  220. sleep 25
  221. done
  222. EOF
  223. chmod +x "$LIMITER_SCRIPT"
  224. cat > "$LIMITER_SERVICE" << EOF
  225. [Unit]
  226. Description=FirewallFalcon Active User Limiter
  227. After=network.target
  228. [Service]
  229. Type=simple
  230. ExecStart=$LIMITER_SCRIPT
  231. Restart=always
  232. RestartSec=5
  233. [Install]
  234. WantedBy=multi-user.target
  235. EOF
  236. # Force kill any old limiter process to prevent systemctl restart hanging
  237. pkill -f "firewallfalcon-limiter" 2>/dev/null
  238. if ! systemctl is-active --quiet firewallfalcon-limiter; then
  239. systemctl daemon-reload
  240. systemctl enable firewallfalcon-limiter &>/dev/null
  241. systemctl start firewallfalcon-limiter --no-block &>/dev/null
  242. else
  243. # Restart if already running to apply new logic
  244. systemctl restart firewallfalcon-limiter --no-block &>/dev/null
  245. fi
  246. }
  247. generate_dns_record() {
  248. echo -e "\n${C_BLUE}⚙️ Generating a random domain...${C_RESET}"
  249. if ! command -v jq &> /dev/null; then
  250. echo -e "${C_YELLOW}⚠️ jq not found, attempting to install...${C_RESET}"
  251. apt-get update > /dev/null 2>&1 && apt-get install -y jq || {
  252. echo -e "${C_RED}❌ Failed to install jq. Cannot manage DNS records.${C_RESET}"
  253. return 1
  254. }
  255. fi
  256. local SERVER_IPV4
  257. SERVER_IPV4=$(curl -s -4 icanhazip.com)
  258. if ! _is_valid_ipv4 "$SERVER_IPV4"; then
  259. echo -e "\n${C_RED}❌ Error: Could not retrieve a valid public IPv4 address from icanhazip.com.${C_RESET}"
  260. echo -e "${C_YELLOW}ℹ️ Please check your server's network connection and DNS resolver settings.${C_RESET}"
  261. echo -e " Output received: '$SERVER_IPV4'"
  262. return 1
  263. fi
  264. local SERVER_IPV6
  265. SERVER_IPV6=$(curl -s -6 icanhazip.com --max-time 5)
  266. local RANDOM_SUBDOMAIN="vps-$(head /dev/urandom | tr -dc a-z0-9 | head -c 8)"
  267. local FULL_DOMAIN="$RANDOM_SUBDOMAIN.$DESEC_DOMAIN"
  268. local HAS_IPV6="false"
  269. local API_DATA
  270. API_DATA=$(printf '[{"subname": "%s", "type": "A", "ttl": 3600, "records": ["%s"]}]' "$RANDOM_SUBDOMAIN" "$SERVER_IPV4")
  271. if [[ -n "$SERVER_IPV6" ]]; then
  272. local aaaa_record
  273. aaaa_record=$(printf ',{"subname": "%s", "type": "AAAA", "ttl": 3600, "records": ["%s"]}' "$RANDOM_SUBDOMAIN" "$SERVER_IPV6")
  274. API_DATA="${API_DATA%?}${aaaa_record}]"
  275. HAS_IPV6="true"
  276. fi
  277. local CREATE_RESPONSE
  278. CREATE_RESPONSE=$(curl -s -w "%{http_code}" -X POST "https://desec.io/api/v1/domains/$DESEC_DOMAIN/rrsets/" \
  279. -H "Authorization: Token $DESEC_TOKEN" -H "Content-Type: application/json" \
  280. --data "$API_DATA")
  281. local HTTP_CODE=${CREATE_RESPONSE: -3}
  282. local RESPONSE_BODY=${CREATE_RESPONSE:0:${#CREATE_RESPONSE}-3}
  283. if [[ "$HTTP_CODE" -ne 201 ]]; then
  284. echo -e "${C_RED}❌ Failed to create DNS records. API returned HTTP $HTTP_CODE.${C_RESET}"
  285. if ! echo "$RESPONSE_BODY" | jq . > /dev/null 2>&1; then
  286. echo "Raw Response: $RESPONSE_BODY"
  287. else
  288. echo "Response: $RESPONSE_BODY" | jq
  289. fi
  290. return 1
  291. fi
  292. cat > "$DNS_INFO_FILE" <<-EOF
  293. SUBDOMAIN="$RANDOM_SUBDOMAIN"
  294. FULL_DOMAIN="$FULL_DOMAIN"
  295. HAS_IPV6="$HAS_IPV6"
  296. EOF
  297. echo -e "\n${C_GREEN}✅ Successfully created domain: ${C_YELLOW}$FULL_DOMAIN${C_RESET}"
  298. }
  299. delete_dns_record() {
  300. if [ ! -f "$DNS_INFO_FILE" ]; then
  301. echo -e "\n${C_YELLOW}ℹ️ No domain to delete.${C_RESET}"
  302. return
  303. fi
  304. echo -e "\n${C_BLUE}🗑️ Deleting DNS records...${C_RESET}"
  305. source "$DNS_INFO_FILE"
  306. if [[ -z "$SUBDOMAIN" ]]; then
  307. echo -e "${C_RED}❌ Could not read record details from config file. Skipping deletion.${C_RESET}"
  308. return
  309. fi
  310. curl -s -X DELETE "https://desec.io/api/v1/domains/$DESEC_DOMAIN/rrsets/$SUBDOMAIN/A/" \
  311. -H "Authorization: Token $DESEC_TOKEN" > /dev/null
  312. if [[ "$HAS_IPV6" == "true" ]]; then
  313. curl -s -X DELETE "https://desec.io/api/v1/domains/$DESEC_DOMAIN/rrsets/$SUBDOMAIN/AAAA/" \
  314. -H "Authorization: Token $DESEC_TOKEN" > /dev/null
  315. fi
  316. echo -e "\n${C_GREEN}✅ Deleted domain: ${C_YELLOW}$FULL_DOMAIN${C_RESET}"
  317. rm -f "$DNS_INFO_FILE"
  318. }
  319. dns_menu() {
  320. clear; show_banner
  321. echo -e "${C_BOLD}${C_PURPLE}--- 🌐 DNS Domain Management ---${C_RESET}"
  322. if [ -f "$DNS_INFO_FILE" ]; then
  323. source "$DNS_INFO_FILE"
  324. echo -e "\nℹ️ A domain already exists for this server:"
  325. echo -e " - ${C_CYAN}Domain:${C_RESET} ${C_YELLOW}$FULL_DOMAIN${C_RESET}"
  326. echo
  327. read -p "👉 Do you want to DELETE this domain? (y/n): " choice
  328. if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
  329. delete_dns_record
  330. else
  331. echo -e "\n${C_YELLOW}❌ Action cancelled.${C_RESET}"
  332. fi
  333. else
  334. echo -e "\nℹ️ No domain has been generated for this server yet."
  335. echo
  336. read -p "👉 Do you want to generate a new random domain now? (y/n): " choice
  337. if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
  338. generate_dns_record
  339. else
  340. echo -e "\n${C_YELLOW}❌ Action cancelled.${C_RESET}"
  341. fi
  342. fi
  343. }
  344. _select_user_interface() {
  345. local title="$1"
  346. clear; show_banner
  347. echo -e "${C_BOLD}${C_PURPLE}${title}${C_RESET}\n"
  348. if [[ ! -s $DB_FILE ]]; then
  349. echo -e "${C_YELLOW}ℹ️ No users found in the database.${C_RESET}"
  350. SELECTED_USER="NO_USERS"; return
  351. fi
  352. read -p "👉 Enter a search term (or press Enter to list all): " search_term
  353. if [[ -z "$search_term" ]]; then
  354. mapfile -t users < <(cut -d: -f1 "$DB_FILE" | sort)
  355. else
  356. mapfile -t users < <(cut -d: -f1 "$DB_FILE" | grep -i "$search_term" | sort)
  357. fi
  358. if [ ${#users[@]} -eq 0 ]; then
  359. echo -e "\n${C_YELLOW}ℹ️ No users found matching your criteria.${C_RESET}"
  360. SELECTED_USER="NO_USERS"; return
  361. fi
  362. echo -e "\nPlease select a user:\n"
  363. for i in "${!users[@]}"; do
  364. printf " ${C_GREEN}[%2d]${C_RESET} %s\n" "$((i+1))" "${users[$i]}"
  365. done
  366. echo -e "\n ${C_RED} [ 0]${C_RESET} ↩️ Cancel and return to main menu"
  367. echo
  368. local choice
  369. while true; do
  370. read -p "👉 Enter the number of the user: " choice
  371. if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 0 ] && [ "$choice" -le "${#users[@]}" ]; then
  372. if [ "$choice" -eq 0 ]; then
  373. SELECTED_USER=""; return
  374. else
  375. SELECTED_USER="${users[$((choice-1))]}"; return
  376. fi
  377. else
  378. echo -e "${C_RED}❌ Invalid selection. Please try again.${C_RESET}"
  379. fi
  380. done
  381. }
  382. get_user_status() {
  383. local username="$1"
  384. if ! id "$username" &>/dev/null; then echo -e "${C_RED}Not Found${C_RESET}"; return; fi
  385. local expiry_date=$(grep "^$username:" "$DB_FILE" | cut -d: -f3)
  386. if passwd -S "$username" 2>/dev/null | grep -q " L "; then echo -e "${C_YELLOW}🔒 Locked${C_RESET}"; return; fi
  387. local expiry_ts=$(date -d "$expiry_date" +%s 2>/dev/null || echo 0)
  388. local current_ts=$(date +%s)
  389. if [[ $expiry_ts -lt $current_ts ]]; then echo -e "${C_RED}🗓️ Expired${C_RESET}"; return; fi
  390. echo -e "${C_GREEN}🟢 Active${C_RESET}"
  391. }
  392. create_user() {
  393. clear; show_banner
  394. echo -e "${C_BOLD}${C_PURPLE}--- ✨ Create New SSH User ---${C_RESET}"
  395. read -p "👉 Enter username (or '0' to cancel): " username
  396. if [[ "$username" == "0" ]]; then
  397. echo -e "\n${C_YELLOW}❌ User creation cancelled.${C_RESET}"
  398. return
  399. fi
  400. if [[ -z "$username" ]]; then
  401. echo -e "\n${C_RED}❌ Error: Username cannot be empty.${C_RESET}"
  402. return
  403. fi
  404. if id "$username" &>/dev/null || grep -q "^$username:" "$DB_FILE"; then
  405. echo -e "\n${C_RED}❌ Error: User '$username' already exists.${C_RESET}"; return
  406. fi
  407. local password=""
  408. while true; do
  409. read -p "🔑 Enter new password: " password
  410. if [[ -z "$password" ]]; then
  411. echo -e "${C_RED}❌ Password cannot be empty. Please try again.${C_RESET}"
  412. else
  413. break
  414. fi
  415. done
  416. read -p "🗓️ Enter account duration (in days): " days
  417. if ! [[ "$days" =~ ^[0-9]+$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
  418. read -p "📶 Enter simultaneous connection limit: " limit
  419. if ! [[ "$limit" =~ ^[0-9]+$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
  420. local expire_date
  421. expire_date=$(date -d "+$days days" +%Y-%m-%d)
  422. useradd -m -s /usr/sbin/nologin "$username"; echo "$username:$password" | chpasswd; chage -E "$expire_date" "$username"
  423. echo "$username:$password:$expire_date:$limit" >> "$DB_FILE"
  424. clear; show_banner
  425. echo -e "${C_GREEN}✅ User '$username' created successfully!${C_RESET}\n"
  426. echo -e " - 👤 Username: ${C_YELLOW}$username${C_RESET}"
  427. echo -e " - 🔑 Password: ${C_YELLOW}$password${C_RESET}"
  428. echo -e " - 🗓️ Expires on: ${C_YELLOW}$expire_date${C_RESET}"
  429. echo -e " - 📶 Connection Limit: ${C_YELLOW}$limit${C_RESET}"
  430. echo -e " ${C_DIM}(Active monitoring service will enforce this limit)${C_RESET}"
  431. # Auto-ask for config generation
  432. echo
  433. read -p "👉 Do you want to generate a client connection config for this user? (y/n): " gen_conf
  434. if [[ "$gen_conf" == "y" || "$gen_conf" == "Y" ]]; then
  435. generate_client_config "$username" "$password"
  436. fi
  437. }
  438. delete_user() {
  439. _select_user_interface "--- 🗑️ Delete a User (from DB) ---"
  440. local username=$SELECTED_USER
  441. if [[ "$username" == "NO_USERS" ]] || [[ -z "$username" ]]; then
  442. if [[ "$username" == "NO_USERS" ]]; then
  443. echo -e "\n${C_YELLOW}ℹ️ No users found in database.${C_RESET}"
  444. fi
  445. read -p "👉 Type username to MANUALLY delete (or '0' to cancel): " manual_user
  446. if [[ "$manual_user" == "0" ]] || [[ -z "$manual_user" ]]; then
  447. echo -e "\n${C_YELLOW}❌ Action cancelled.${C_RESET}"
  448. return
  449. fi
  450. username="$manual_user"
  451. if ! id "$username" &>/dev/null; then
  452. echo -e "\n${C_RED}❌ Error: User '$username' does not exist on this system.${C_RESET}"
  453. return
  454. fi
  455. if grep -q "^$username:" "$DB_FILE"; then
  456. echo -e "\n${C_YELLOW}ℹ️ User '$username' is in the database. Please use the normal selection method.${C_RESET}"
  457. echo -e " For safety, manual deletion is only for users NOT in the database."
  458. return
  459. fi
  460. echo -e "${C_YELLOW}⚠️ User '$username' exists on the system but is NOT in the database.${C_RESET}"
  461. fi
  462. read -p "👉 Are you sure you want to PERMANENTLY delete '$username'? (y/n): " confirm
  463. if [[ "$confirm" != "y" ]]; then echo -e "\n${C_YELLOW}❌ Deletion cancelled.${C_RESET}"; return; fi
  464. echo -e "${C_BLUE}🔌 Force killing active connections for $username...${C_RESET}"
  465. killall -u "$username" -9 &>/dev/null
  466. sleep 1
  467. userdel -r "$username" &>/dev/null
  468. if [ $? -eq 0 ]; then
  469. echo -e "\n${C_GREEN}✅ System user '$username' has been deleted.${C_RESET}"
  470. else
  471. echo -e "\n${C_RED}❌ Failed to delete system user '$username'.${C_RESET}"
  472. fi
  473. sed -i "/^$username:/d" "$DB_FILE"
  474. echo -e "${C_GREEN}✅ User '$username' has been completely removed.${C_RESET}"
  475. }
  476. edit_user() {
  477. _select_user_interface "--- ✏️ Edit a User ---"
  478. local username=$SELECTED_USER
  479. if [[ "$username" == "NO_USERS" ]] || [[ -z "$username" ]]; then return; fi
  480. while true; do
  481. clear; show_banner; echo -e "${C_BOLD}${C_PURPLE}--- Editing User: ${C_YELLOW}$username${C_PURPLE} ---${C_RESET}"
  482. echo -e "\nSelect a detail to edit:\n"
  483. printf " ${C_GREEN}[ 1]${C_RESET} %-35s\n" "🔑 Change Password"
  484. printf " ${C_GREEN}[ 2]${C_RESET} %-35s\n" "🗓️ Change Expiration Date"
  485. printf " ${C_GREEN}[ 3]${C_RESET} %-35s\n" "📶 Change Connection Limit"
  486. echo -e "\n ${C_RED}[ 0]${C_RESET} ✅ Finish Editing"; echo; read -p "👉 Enter your choice: " edit_choice
  487. case $edit_choice in
  488. 1)
  489. local new_pass=""
  490. while true; do
  491. read -p "Enter new password: " new_pass
  492. if [[ -z "$new_pass" ]]; then
  493. echo -e "${C_RED}❌ Password cannot be empty. Please try again.${C_RESET}"
  494. else
  495. break
  496. fi
  497. done
  498. echo "$username:$new_pass" | chpasswd
  499. local current_line; current_line=$(grep "^$username:" "$DB_FILE"); local expiry; expiry=$(echo "$current_line" | cut -d: -f3); local limit; limit=$(echo "$current_line" | cut -d: -f4)
  500. sed -i "s/^$username:.*/$username:$new_pass:$expiry:$limit/" "$DB_FILE"
  501. echo -e "\n${C_GREEN}✅ Password for '$username' changed successfully.${C_RESET}"
  502. echo -e "New Password: ${C_YELLOW}$new_pass${C_RESET}"
  503. ;;
  504. 2) read -p "Enter new duration (in days from today): " days
  505. if [[ "$days" =~ ^[0-9]+$ ]]; then
  506. local new_expire_date; new_expire_date=$(date -d "+$days days" +%Y-%m-%d); chage -E "$new_expire_date" "$username"
  507. local current_line; current_line=$(grep "^$username:" "$DB_FILE"); local pass; pass=$(echo "$current_line" | cut -d: -f2); local limit; limit=$(echo "$current_line" | cut -d: -f4)
  508. sed -i "s/^$username:.*/$username:$pass:$new_expire_date:$limit/" "$DB_FILE"
  509. echo -e "\n${C_GREEN}✅ Expiration for '$username' set to ${C_YELLOW}$new_expire_date${C_RESET}."
  510. else echo -e "\n${C_RED}❌ Invalid number of days.${C_RESET}"; fi ;;
  511. 3) read -p "Enter new simultaneous connection limit: " new_limit
  512. if [[ "$new_limit" =~ ^[0-9]+$ ]]; then
  513. local current_line; current_line=$(grep "^$username:" "$DB_FILE"); local pass; pass=$(echo "$current_line" | cut -d: -f2); local expiry; expiry=$(echo "$current_line" | cut -d: -f3)
  514. sed -i "s/^$username:.*/$username:$pass:$expiry:$new_limit/" "$DB_FILE"
  515. echo -e "\n${C_GREEN}✅ Connection limit for '$username' set to ${C_YELLOW}$new_limit${C_RESET}."
  516. else echo -e "\n${C_RED}❌ Invalid limit.${C_RESET}"; fi ;;
  517. 0) return ;;
  518. *) echo -e "\n${C_RED}❌ Invalid option.${C_RESET}" ;;
  519. esac
  520. echo -e "\nPress ${C_YELLOW}[Enter]${C_RESET} to continue editing..." && read -r
  521. done
  522. }
  523. lock_user() {
  524. _select_user_interface "--- 🔒 Lock a User (from DB) ---"
  525. local u=$SELECTED_USER
  526. if [[ "$u" == "NO_USERS" ]] || [[ -z "$u" ]]; then
  527. if [[ "$u" == "NO_USERS" ]]; then
  528. echo -e "\n${C_YELLOW}ℹ️ No users found in database.${C_RESET}"
  529. fi
  530. read -p "👉 Type username to MANUALLY lock (or '0' to cancel): " manual_user
  531. if [[ "$manual_user" == "0" ]] || [[ -z "$manual_user" ]]; then
  532. echo -e "\n${C_YELLOW}❌ Action cancelled.${C_RESET}"
  533. return
  534. fi
  535. u="$manual_user"
  536. if ! id "$u" &>/dev/null; then
  537. echo -e "\n${C_RED}❌ Error: User '$u' does not exist on this system.${C_RESET}"
  538. return
  539. fi
  540. if grep -q "^$u:" "$DB_FILE"; then
  541. echo -e "\n${C_YELLOW}ℹ️ User '$u' is in the database. Use the normal selection method.${C_RESET}"
  542. else
  543. echo -e "${C_YELLOW}⚠️ User '$u' exists on the system but is NOT in the database.${C_RESET}"
  544. fi
  545. fi
  546. usermod -L "$u"
  547. if [ $? -eq 0 ]; then
  548. killall -u "$u" -9 &>/dev/null
  549. echo -e "\n${C_GREEN}✅ User '$u' has been locked and active sessions killed.${C_RESET}"
  550. else
  551. echo -e "\n${C_RED}❌ Failed to lock user '$u'.${C_RESET}"
  552. fi
  553. }
  554. unlock_user() {
  555. _select_user_interface "--- 🔓 Unlock a User (from DB) ---"
  556. local u=$SELECTED_USER
  557. if [[ "$u" == "NO_USERS" ]] || [[ -z "$u" ]]; then
  558. if [[ "$u" == "NO_USERS" ]]; then
  559. echo -e "\n${C_YELLOW}ℹ️ No users found in database.${C_RESET}"
  560. fi
  561. read -p "👉 Type username to MANUALLY unlock (or '0' to cancel): " manual_user
  562. if [[ "$manual_user" == "0" ]] || [[ -z "$manual_user" ]]; then
  563. echo -e "\n${C_YELLOW}❌ Action cancelled.${C_RESET}"
  564. return
  565. fi
  566. u="$manual_user"
  567. if ! id "$u" &>/dev/null; then
  568. echo -e "\n${C_RED}❌ Error: User '$u' does not exist on this system.${C_RESET}"
  569. return
  570. fi
  571. if grep -q "^$u:" "$DB_FILE"; then
  572. echo -e "\n${C_YELLOW}ℹ️ User '$u' is in the database. Use the normal selection method.${C_RESET}"
  573. else
  574. echo -e "${C_YELLOW}⚠️ User '$u' exists on the system but is NOT in the database.${C_RESET}"
  575. fi
  576. fi
  577. usermod -U "$u"
  578. if [ $? -eq 0 ]; then
  579. echo -e "\n${C_GREEN}✅ User '$u' has been unlocked.${C_RESET}"
  580. else
  581. echo -e "\n${C_RED}❌ Failed to unlock user '$u'.${C_RESET}"
  582. fi
  583. }
  584. list_users() {
  585. clear; show_banner
  586. if [[ ! -s "$DB_FILE" ]]; then
  587. echo -e "\n${C_YELLOW}ℹ️ No users are currently being managed.${C_RESET}"
  588. return
  589. fi
  590. echo -e "${C_BOLD}${C_PURPLE}--- 📋 Managed Users ---${C_RESET}"
  591. echo -e "${C_CYAN}======================================================================${C_RESET}"
  592. printf "${C_BOLD}${C_WHITE}%-20s | %-12s | %-15s | %-20s${C_RESET}\n" "USERNAME" "EXPIRES" "CONNECTIONS" "STATUS"
  593. echo -e "${C_CYAN}----------------------------------------------------------------------${C_RESET}"
  594. while IFS=: read -r user pass expiry limit; do
  595. local online_count
  596. online_count=$(pgrep -u "$user" sshd | wc -l)
  597. local status
  598. status=$(get_user_status "$user")
  599. local plain_status
  600. plain_status=$(echo -e "$status" | sed 's/\x1b\[[0-9;]*m//g')
  601. local connection_string="$online_count / $limit"
  602. local line_color="$C_WHITE"
  603. case $plain_status in
  604. *"Active"*) line_color="$C_GREEN" ;;
  605. *"Locked"*) line_color="$C_YELLOW" ;;
  606. *"Expired"*) line_color="$C_RED" ;;
  607. *"Not Found"*) line_color="$C_DIM" ;;
  608. esac
  609. printf "${line_color}%-20s ${C_RESET}| ${C_YELLOW}%-12s ${C_RESET}| ${C_CYAN}%-15s ${C_RESET}| %-20s\n" "$user" "$expiry" "$connection_string" "$status"
  610. done < <(sort "$DB_FILE")
  611. echo -e "${C_CYAN}======================================================================${C_RESET}\n"
  612. }
  613. renew_user() {
  614. _select_user_interface "--- 🔄 Renew a User ---"; local u=$SELECTED_USER; if [[ "$u" == "NO_USERS" || -z "$u" ]]; then return; fi
  615. read -p "👉 Enter number of days to extend the account: " days; if ! [[ "$days" =~ ^[0-9]+$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
  616. local new_expire_date; new_expire_date=$(date -d "+$days days" +%Y-%m-%d); chage -E "$new_expire_date" "$u"
  617. local line; line=$(grep "^$u:" "$DB_FILE"); local pass; pass=$(echo "$line"|cut -d: -f2); local limit; limit=$(echo "$line"|cut -d: -f4)
  618. sed -i "s/^$u:.*/$u:$pass:$new_expire_date:$limit/" "$DB_FILE"
  619. echo -e "\n${C_GREEN}✅ User '$u' has been renewed. New expiration date is ${C_YELLOW}${new_expire_date}${C_RESET}."
  620. }
  621. cleanup_expired() {
  622. clear; show_banner
  623. echo -e "${C_BOLD}${C_PURPLE}--- 🧹 Cleanup Expired Users ---${C_RESET}"
  624. local expired_users=()
  625. local current_ts
  626. current_ts=$(date +%s)
  627. if [[ ! -s "$DB_FILE" ]]; then
  628. echo -e "\n${C_GREEN}✅ User database is empty. No expired users found.${C_RESET}"
  629. return
  630. fi
  631. while IFS=: read -r user pass expiry limit; do
  632. local expiry_ts
  633. expiry_ts=$(date -d "$expiry" +%s 2>/dev/null || echo 0)
  634. if [[ $expiry_ts -lt $current_ts && $expiry_ts -ne 0 ]]; then
  635. expired_users+=("$user")
  636. fi
  637. done < "$DB_FILE"
  638. if [ ${#expired_users[@]} -eq 0 ]; then
  639. echo -e "\n${C_GREEN}✅ No expired users found.${C_RESET}"
  640. return
  641. fi
  642. echo -e "\nThe following users have expired: ${C_RED}${expired_users[*]}${C_RESET}"
  643. read -p "👉 Do you want to delete all of them? (y/n): " confirm
  644. if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
  645. for user in "${expired_users[@]}"; do
  646. echo " - Deleting ${C_YELLOW}$user...${C_RESET}"
  647. killall -u "$user" -9 &>/dev/null
  648. userdel -r "$user" &>/dev/null
  649. sed -i "/^$user:/d" "$DB_FILE"
  650. done
  651. echo -e "\n${C_GREEN}✅ Expired users have been cleaned up.${C_RESET}"
  652. else
  653. echo -e "\n${C_YELLOW}❌ Cleanup cancelled.${C_RESET}"
  654. fi
  655. }
  656. backup_user_data() {
  657. clear; show_banner
  658. echo -e "${C_BOLD}${C_PURPLE}--- 💾 Backup User Data ---${C_RESET}"
  659. read -p "👉 Enter path for backup file [/root/firewallfalcon_users.tar.gz]: " backup_path
  660. backup_path=${backup_path:-/root/firewallfalcon_users.tar.gz}
  661. if [ ! -d "$DB_DIR" ] || [ ! -s "$DB_FILE" ]; then
  662. echo -e "\n${C_YELLOW}ℹ️ No user data found to back up.${C_RESET}"
  663. return
  664. fi
  665. echo -e "\n${C_BLUE}⚙️ Backing up user database and settings to ${C_YELLOW}$backup_path${C_RESET}..."
  666. tar -czf "$backup_path" -C "$(dirname "$DB_DIR")" "$(basename "$DB_DIR")"
  667. if [ $? -eq 0 ]; then
  668. echo -e "\n${C_GREEN}✅ SUCCESS: User data backup created at ${C_YELLOW}$backup_path${C_RESET}"
  669. else
  670. echo -e "\n${C_RED}❌ ERROR: Backup failed.${C_RESET}"
  671. fi
  672. }
  673. restore_user_data() {
  674. clear; show_banner
  675. echo -e "${C_BOLD}${C_PURPLE}--- 📥 Restore User Data ---${C_RESET}"
  676. read -p "👉 Enter the full path to the user data backup file [/root/firewallfalcon_users.tar.gz]: " backup_path
  677. backup_path=${backup_path:-/root/firewallfalcon_users.tar.gz}
  678. if [ ! -f "$backup_path" ]; then
  679. echo -e "\n${C_RED}❌ ERROR: Backup file not found at '$backup_path'.${C_RESET}"
  680. return
  681. fi
  682. echo -e "\n${C_RED}${C_BOLD}⚠️ WARNING:${C_RESET} This will overwrite all current users and settings."
  683. echo -e "It will restore user accounts, passwords, limits, and expiration dates from the backup file."
  684. read -p "👉 Are you absolutely sure you want to proceed? (y/n): " confirm
  685. if [[ "$confirm" != "y" ]]; then echo -e "\n${C_YELLOW}❌ Restore cancelled.${C_RESET}"; return; fi
  686. local temp_dir
  687. temp_dir=$(mktemp -d)
  688. echo -e "\n${C_BLUE}⚙️ Extracting backup file to a temporary location...${C_RESET}"
  689. tar -xzf "$backup_path" -C "$temp_dir"
  690. if [ $? -ne 0 ]; then
  691. echo -e "\n${C_RED}❌ ERROR: Failed to extract backup file. Aborting.${C_RESET}"
  692. rm -rf "$temp_dir"
  693. return
  694. fi
  695. local restored_db_file="$temp_dir/firewallfalcon/users.db"
  696. if [ ! -f "$restored_db_file" ]; then
  697. echo -e "\n${C_RED}❌ ERROR: users.db not found in the backup. Cannot restore user accounts.${C_RESET}"
  698. rm -rf "$temp_dir"
  699. return
  700. fi
  701. echo -e "${C_BLUE}⚙️ Overwriting current user database...${C_RESET}"
  702. mkdir -p "$DB_DIR"
  703. cp "$restored_db_file" "$DB_FILE"
  704. if [ -d "$temp_dir/firewallfalcon/ssl" ]; then
  705. cp -r "$temp_dir/firewallfalcon/ssl" "$DB_DIR/"
  706. fi
  707. if [ -d "$temp_dir/firewallfalcon/dnstt" ]; then
  708. cp -r "$temp_dir/firewallfalcon/dnstt" "$DB_DIR/"
  709. fi
  710. if [ -f "$temp_dir/firewallfalcon/dns_info.conf" ]; then
  711. cp "$temp_dir/firewallfalcon/dns_info.conf" "$DB_DIR/"
  712. fi
  713. if [ -f "$temp_dir/firewallfalcon/dnstt_info.conf" ]; then
  714. cp "$temp_dir/firewallfalcon/dnstt_info.conf" "$DB_DIR/"
  715. fi
  716. if [ -f "$temp_dir/firewallfalcon/falconproxy_config.conf" ]; then
  717. cp "$temp_dir/firewallfalcon/falconproxy_config.conf" "$DB_DIR/"
  718. fi
  719. echo -e "${C_BLUE}⚙️ Re-synchronizing system accounts with the restored database...${C_RESET}"
  720. while IFS=: read -r user pass expiry limit; do
  721. echo "Processing user: ${C_YELLOW}$user${C_RESET}"
  722. if ! id "$user" &>/dev/null; then
  723. echo " - User does not exist in system. Creating..."
  724. useradd -m -s /usr/sbin/nologin "$user"
  725. fi
  726. echo " - Setting password..."
  727. echo "$user:$pass" | chpasswd
  728. echo " - Setting expiration to $expiry..."
  729. chage -E "$expiry" "$user"
  730. echo " - Connection limit is $limit (enforced by PAM)"
  731. done < "$DB_FILE"
  732. rm -rf "$temp_dir"
  733. echo -e "\n${C_GREEN}✅ SUCCESS: User data restore completed.${C_RESET}"
  734. }
  735. _enable_banner_in_sshd_config() {
  736. echo -e "\n${C_BLUE}⚙️ Configuring sshd_config...${C_RESET}"
  737. sed -i.bak -E 's/^( *Banner *).*/#\1/' /etc/ssh/sshd_config
  738. if ! grep -q -E "^Banner $SSH_BANNER_FILE" /etc/ssh/sshd_config; then
  739. echo -e "\n# FirewallFalcon SSH Banner\nBanner $SSH_BANNER_FILE" >> /etc/ssh/sshd_config
  740. fi
  741. echo -e "${C_GREEN}✅ sshd_config updated.${C_RESET}"
  742. }
  743. _restart_ssh() {
  744. echo -e "\n${C_BLUE}🔄 Restarting SSH service to apply changes...${C_RESET}"
  745. local ssh_service_name=""
  746. if [ -f /lib/systemd/system/sshd.service ]; then
  747. ssh_service_name="sshd.service"
  748. elif [ -f /lib/systemd/system/ssh.service ]; then
  749. ssh_service_name="ssh.service"
  750. else
  751. echo -e "${C_RED}❌ Could not find sshd.service or ssh.service. Cannot restart SSH.${C_RESET}"
  752. return 1
  753. fi
  754. systemctl restart "${ssh_service_name}"
  755. if [ $? -eq 0 ]; then
  756. echo -e "${C_GREEN}✅ SSH service ('${ssh_service_name}') restarted successfully.${C_RESET}"
  757. else
  758. echo -e "${C_RED}❌ Failed to restart SSH service ('${ssh_service_name}'). Please check 'journalctl -u ${ssh_service_name}' for errors.${C_RESET}"
  759. fi
  760. }
  761. set_ssh_banner_paste() {
  762. clear; show_banner
  763. echo -e "${C_BOLD}${C_PURPLE}--- 📋 Paste SSH Banner ---${C_RESET}"
  764. echo -e "Paste your banner code below. Press ${C_YELLOW}[Ctrl+D]${C_RESET} when you are finished."
  765. echo -e "${C_DIM}The current banner (if any) will be overwritten.${C_RESET}"
  766. echo -e "--------------------------------------------------"
  767. cat > "$SSH_BANNER_FILE"
  768. chmod 644 "$SSH_BANNER_FILE"
  769. echo -e "\n--------------------------------------------------"
  770. echo -e "\n${C_GREEN}✅ Banner content saved from paste.${C_RESET}"
  771. _enable_banner_in_sshd_config
  772. _restart_ssh
  773. echo -e "\nPress ${C_YELLOW}[Enter]${C_RESET} to return..." && read -r
  774. }
  775. view_ssh_banner() {
  776. clear; show_banner
  777. echo -e "${C_BOLD}${C_PURPLE}--- 👁️ Current SSH Banner ---${C_RESET}"
  778. if [ -f "$SSH_BANNER_FILE" ]; then
  779. echo -e "\n${C_CYAN}--- BEGIN BANNER ---${C_RESET}"
  780. cat "$SSH_BANNER_FILE"
  781. echo -e "${C_CYAN}---- END BANNER ----${C_RESET}"
  782. else
  783. echo -e "\n${C_YELLOW}ℹ️ No banner file found at $SSH_BANNER_FILE.${C_RESET}"
  784. fi
  785. echo -e "\nPress ${C_YELLOW}[Enter]${C_RESET} to return..." && read -r
  786. }
  787. remove_ssh_banner() {
  788. clear; show_banner
  789. echo -e "${C_BOLD}${C_PURPLE}--- 🗑️ Remove SSH Banner ---${C_RESET}"
  790. read -p "👉 Are you sure you want to disable and remove the SSH banner? (y/n): " confirm
  791. if [[ "$confirm" != "y" ]]; then
  792. echo -e "\n${C_YELLOW}❌ Action cancelled.${C_RESET}"
  793. echo -e "\nPress ${C_YELLOW}[Enter]${C_RESET} to return..." && read -r
  794. return
  795. fi
  796. if [ -f "$SSH_BANNER_FILE" ]; then
  797. rm -f "$SSH_BANNER_FILE"
  798. echo -e "\n${C_GREEN}✅ Removed banner file: $SSH_BANNER_FILE${C_RESET}"
  799. else
  800. echo -e "\n${C_YELLOW}ℹ️ No banner file to remove.${C_RESET}"
  801. fi
  802. echo -e "\n${C_BLUE}⚙️ Disabling banner in sshd_config...${C_RESET}"
  803. sed -i.bak -E "s/^( *Banner\s+$SSH_BANNER_FILE)/#\1/" /etc/ssh/sshd_config
  804. echo -e "${C_GREEN}✅ Banner disabled in configuration.${C_RESET}"
  805. _restart_ssh
  806. echo -e "\nPress ${C_YELLOW}[Enter]${C_RESET} to return..." && read -r
  807. }
  808. ssh_banner_menu() {
  809. while true; do
  810. show_banner
  811. local banner_status
  812. if grep -q -E "^\s*Banner\s+$SSH_BANNER_FILE" /etc/ssh/sshd_config && [ -f "$SSH_BANNER_FILE" ]; then
  813. banner_status="${C_STATUS_A}(Active)${C_RESET}"
  814. else
  815. banner_status="${C_STATUS_I}(Inactive)${C_RESET}"
  816. fi
  817. echo -e "\n ${C_TITLE}═════════════════[ ${C_BOLD}🎨 SSH Banner Management ${banner_status} ${C_RESET}${C_TITLE}]═════════════════${C_RESET}"
  818. printf " ${C_CHOICE}[ 1]${C_RESET} %-40s\n" "📋 Paste or Edit Banner"
  819. printf " ${C_CHOICE}[ 2]${C_RESET} %-40s\n" "👁️ View Current Banner"
  820. printf " ${C_DANGER}[ 3]${C_RESET} %-40s\n" "🗑️ Disable and Remove Banner"
  821. echo -e " ${C_DIM}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~${C_RESET}"
  822. echo -e " ${C_WARN}[ 0]${C_RESET} ↩️ Return to Main Menu"
  823. echo
  824. read -p "$(echo -e ${C_PROMPT}"👉 Select an option: "${C_RESET})" choice
  825. case $choice in
  826. 1) set_ssh_banner_paste ;;
  827. 2) view_ssh_banner ;;
  828. 3) remove_ssh_banner ;;
  829. 0) return ;;
  830. *) echo -e "\n${C_RED}❌ Invalid option.${C_RESET}" && sleep 2 ;;
  831. esac
  832. done
  833. }
  834. install_udp_custom() {
  835. clear; show_banner
  836. echo -e "${C_BOLD}${C_PURPLE}--- 🚀 Installing udp-custom ---${C_RESET}"
  837. if [ -f "$UDP_CUSTOM_SERVICE_FILE" ]; then
  838. echo -e "\n${C_YELLOW}ℹ️ udp-custom is already installed.${C_RESET}"
  839. return
  840. fi
  841. echo -e "\n${C_GREEN}⚙️ Creating directory for udp-custom...${C_RESET}"
  842. rm -rf "$UDP_CUSTOM_DIR"
  843. mkdir -p "$UDP_CUSTOM_DIR"
  844. echo -e "\n${C_GREEN}⚙️ Detecting system architecture...${C_RESET}"
  845. local arch
  846. arch=$(uname -m)
  847. local binary_url=""
  848. if [[ "$arch" == "x86_64" ]]; then
  849. binary_url="https://github.com/firewallfalcons/FirewallFalcon-Manager/raw/main/udp/udp-custom-linux-amd64"
  850. echo -e "${C_BLUE}ℹ️ Detected x86_64 (amd64) architecture.${C_RESET}"
  851. elif [[ "$arch" == "aarch64" || "$arch" == "arm64" ]]; then
  852. binary_url="https://github.com/firewallfalcons/FirewallFalcon-Manager/raw/main/udp/udp-custom-linux-arm"
  853. echo -e "${C_BLUE}ℹ️ Detected ARM64 architecture.${C_RESET}"
  854. else
  855. echo -e "\n${C_RED}❌ Unsupported architecture: $arch. Cannot install udp-custom.${C_RESET}"
  856. rm -rf "$UDP_CUSTOM_DIR"
  857. return
  858. fi
  859. echo -e "\n${C_GREEN}📥 Downloading udp-custom binary...${C_RESET}"
  860. wget -q --show-progress -O "$UDP_CUSTOM_DIR/udp-custom" "$binary_url"
  861. if [ $? -ne 0 ]; then
  862. echo -e "\n${C_RED}❌ Failed to download the udp-custom binary.${C_RESET}"
  863. rm -rf "$UDP_CUSTOM_DIR"
  864. return
  865. fi
  866. chmod +x "$UDP_CUSTOM_DIR/udp-custom"
  867. echo -e "\n${C_GREEN}📝 Creating default config.json...${C_RESET}"
  868. cat > "$UDP_CUSTOM_DIR/config.json" <<EOF
  869. {
  870. "listen": ":36712",
  871. "stream_buffer": 33554432,
  872. "receive_buffer": 83886080,
  873. "auth": {
  874. "mode": "passwords"
  875. }
  876. }
  877. EOF
  878. chmod 644 "$UDP_CUSTOM_DIR/config.json"
  879. echo -e "\n${C_GREEN}📝 Creating systemd service file...${C_RESET}"
  880. cat > "$UDP_CUSTOM_SERVICE_FILE" <<EOF
  881. [Unit]
  882. Description=UDP Custom by FirewallFalcon
  883. After=network.target
  884. [Service]
  885. User=root
  886. Type=simple
  887. ExecStart=$UDP_CUSTOM_DIR/udp-custom server -exclude 53,5300
  888. WorkingDirectory=$UDP_CUSTOM_DIR/
  889. Restart=always
  890. RestartSec=2s
  891. [Install]
  892. WantedBy=default.target
  893. EOF
  894. echo -e "\n${C_GREEN}▶️ Enabling and starting udp-custom service...${C_RESET}"
  895. systemctl daemon-reload
  896. systemctl enable udp-custom.service
  897. systemctl start udp-custom.service
  898. sleep 2
  899. if systemctl is-active --quiet udp-custom; then
  900. echo -e "\n${C_GREEN}✅ SUCCESS: udp-custom is installed and active.${C_RESET}"
  901. else
  902. echo -e "\n${C_RED}❌ ERROR: udp-custom service failed to start.${C_RESET}"
  903. echo -e "${C_YELLOW}ℹ️ Displaying last 15 lines of the service log for diagnostics:${C_RESET}"
  904. journalctl -u udp-custom.service -n 15 --no-pager
  905. fi
  906. }
  907. uninstall_udp_custom() {
  908. echo -e "\n${C_BOLD}${C_PURPLE}--- 🗑️ Uninstalling udp-custom ---${C_RESET}"
  909. if [ ! -f "$UDP_CUSTOM_SERVICE_FILE" ]; then
  910. echo -e "${C_YELLOW}ℹ️ udp-custom is not installed, skipping.${C_RESET}"
  911. return
  912. fi
  913. echo -e "${C_GREEN}🛑 Stopping and disabling udp-custom service...${C_RESET}"
  914. systemctl stop udp-custom.service >/dev/null 2>&1
  915. systemctl disable udp-custom.service >/dev/null 2>&1
  916. echo -e "${C_GREEN}🗑️ Removing systemd service file...${C_RESET}"
  917. rm -f "$UDP_CUSTOM_SERVICE_FILE"
  918. systemctl daemon-reload
  919. echo -e "${C_GREEN}🗑️ Removing udp-custom directory and files...${C_RESET}"
  920. rm -rf "$UDP_CUSTOM_DIR"
  921. echo -e "${C_GREEN}✅ udp-custom has been uninstalled successfully.${C_RESET}"
  922. }
  923. install_badvpn() {
  924. clear; show_banner
  925. echo -e "${C_BOLD}${C_PURPLE}--- 🚀 Installing badvpn (udpgw) ---${C_RESET}"
  926. if [ -f "$BADVPN_SERVICE_FILE" ]; then
  927. echo -e "\n${C_YELLOW}ℹ️ badvpn is already installed.${C_RESET}"
  928. return
  929. fi
  930. check_and_open_firewall_port 7300 udp || return
  931. echo -e "\n${C_GREEN}🔄 Updating package lists...${C_RESET}"
  932. apt-get update
  933. echo -e "\n${C_GREEN}📦 Installing all required packages...${C_RESET}"
  934. apt-get install -y cmake g++ make screen git build-essential libssl-dev libnspr4-dev libnss3-dev pkg-config
  935. echo -e "\n${C_GREEN}📥 Cloning badvpn from github...${C_RESET}"
  936. git clone https://github.com/ambrop72/badvpn.git "$BADVPN_BUILD_DIR"
  937. cd "$BADVPN_BUILD_DIR" || { echo -e "${C_RED}❌ Failed to change directory to build folder.${C_RESET}"; return; }
  938. echo -e "\n${C_GREEN}⚙️ Running CMake...${C_RESET}"
  939. cmake . || { echo -e "${C_RED}❌ CMake configuration failed.${C_RESET}"; rm -rf "$BADVPN_BUILD_DIR"; return; }
  940. echo -e "\n${C_GREEN}🛠️ Compiling source...${C_RESET}"
  941. make || { echo -e "${C_RED}❌ Compilation (make) failed.${C_RESET}"; rm -rf "$BADVPN_BUILD_DIR"; return; }
  942. local badvpn_binary
  943. badvpn_binary=$(find "$BADVPN_BUILD_DIR" -name "badvpn-udpgw" -type f | head -n 1)
  944. if [[ -z "$badvpn_binary" || ! -f "$badvpn_binary" ]]; then
  945. echo -e "${C_RED}❌ ERROR: Could not find the compiled 'badvpn-udpgw' binary after compilation.${C_RESET}"
  946. rm -rf "$BADVPN_BUILD_DIR"
  947. return
  948. fi
  949. echo -e "${C_GREEN}ℹ️ Found binary at: $badvpn_binary${C_RESET}"
  950. chmod +x "$badvpn_binary"
  951. echo -e "\n${C_GREEN}📝 Creating systemd service file...${C_RESET}"
  952. cat > "$BADVPN_SERVICE_FILE" <<-EOF
  953. [Unit]
  954. Description=BadVPN UDP Gateway
  955. After=network.target
  956. [Service]
  957. ExecStart=$badvpn_binary --listen-addr 0.0.0.0:7300 --max-clients 1000 --max-connections-for-client 8
  958. User=root
  959. Restart=always
  960. RestartSec=3
  961. [Install]
  962. WantedBy=multi-user.target
  963. EOF
  964. echo -e "\n${C_GREEN}▶️ Enabling and starting badvpn service...${C_RESET}"
  965. systemctl daemon-reload
  966. systemctl enable badvpn.service
  967. systemctl start badvpn.service
  968. sleep 2
  969. if systemctl is-active --quiet badvpn; then
  970. echo -e "\n${C_GREEN}✅ SUCCESS: badvpn (udpgw) is installed and active on port 7300.${C_RESET}"
  971. else
  972. echo -e "\n${C_RED}❌ ERROR: badvpn service failed to start.${C_RESET}"
  973. echo -e "${C_YELLOW}ℹ️ Displaying last 15 lines of the service log for diagnostics:${C_RESET}"
  974. journalctl -u badvpn.service -n 15 --no-pager
  975. fi
  976. }
  977. uninstall_badvpn() {
  978. echo -e "\n${C_BOLD}${C_PURPLE}--- 🗑️ Uninstalling badvpn (udpgw) ---${C_RESET}"
  979. if [ ! -f "$BADVPN_SERVICE_FILE" ]; then
  980. echo -e "${C_YELLOW}ℹ️ badvpn is not installed, skipping.${C_RESET}"
  981. return
  982. fi
  983. echo -e "${C_GREEN}🛑 Stopping and disabling badvpn service...${C_RESET}"
  984. systemctl stop badvpn.service >/dev/null 2>&1
  985. systemctl disable badvpn.service >/dev/null 2>&1
  986. echo -e "${C_GREEN}🗑️ Removing systemd service file...${C_RESET}"
  987. rm -f "$BADVPN_SERVICE_FILE"
  988. systemctl daemon-reload
  989. echo -e "${C_GREEN}🗑️ Removing badvpn build directory...${C_RESET}"
  990. rm -rf "$BADVPN_BUILD_DIR"
  991. echo -e "${C_GREEN}✅ badvpn has been uninstalled successfully.${C_RESET}"
  992. }
  993. install_ssl_tunnel() {
  994. clear; show_banner
  995. echo -e "${C_BOLD}${C_PURPLE}--- 🚀 Installing SSL Tunnel (HAProxy) for SSH ---${C_RESET}"
  996. if ! command -v haproxy &> /dev/null; then
  997. echo -e "\n${C_YELLOW}⚠️ HAProxy not found. Installing...${C_RESET}"
  998. apt-get update && apt-get install -y haproxy || { echo -e "${C_RED}❌ Failed to install HAProxy.${C_RESET}"; return; }
  999. fi
  1000. read -p "👉 Enter the port for the SSL tunnel [444]: " ssl_port
  1001. ssl_port=${ssl_port:-444}
  1002. if ! [[ "$ssl_port" =~ ^[0-9]+$ ]] || [ "$ssl_port" -lt 1 ] || [ "$ssl_port" -gt 65535 ]; then
  1003. echo -e "\n${C_RED}❌ Invalid port number. Aborting.${C_RESET}"
  1004. return
  1005. fi
  1006. check_and_free_ports "$ssl_port" || return
  1007. check_and_open_firewall_port "$ssl_port" || return
  1008. if [ -f "$SSL_CERT_FILE" ]; then
  1009. read -p "SSL certificate already exists. Overwrite? (y/n): " overwrite_cert
  1010. if [[ "$overwrite_cert" != "y" ]]; then
  1011. echo -e "${C_YELLOW}ℹ️ Using existing certificate.${C_RESET}"
  1012. else
  1013. rm -f "$SSL_CERT_FILE"
  1014. fi
  1015. fi
  1016. if [ ! -f "$SSL_CERT_FILE" ]; then
  1017. echo -e "\n${C_GREEN}🔐 Generating self-signed SSL certificate...${C_RESET}"
  1018. openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
  1019. -keyout "$SSL_CERT_FILE" -out "$SSL_CERT_FILE" \
  1020. -subj "/CN=@FIREWALLFALCON" \
  1021. >/dev/null 2>&1 || { echo -e "${C_RED}❌ Failed to generate SSL certificate.${C_RESET}"; return; }
  1022. echo -e "${C_GREEN}✅ Certificate created: ${C_YELLOW}$SSL_CERT_FILE${C_RESET}"
  1023. fi
  1024. echo -e "\n${C_GREEN}📝 Creating HAProxy configuration for port $ssl_port...${C_RESET}"
  1025. cat > "$HAPROXY_CONFIG" <<-EOF
  1026. global
  1027. log /dev/log local0
  1028. log /dev/log local1 notice
  1029. chroot /var/lib/haproxy
  1030. stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
  1031. stats timeout 30s
  1032. user haproxy
  1033. group haproxy
  1034. daemon
  1035. defaults
  1036. log global
  1037. mode tcp
  1038. option tcplog
  1039. option dontlognull
  1040. timeout connect 5000
  1041. timeout client 50000
  1042. timeout server 50000
  1043. frontend ssh_ssl_in
  1044. bind *:$ssl_port ssl crt $SSL_CERT_FILE
  1045. mode tcp
  1046. default_backend ssh_backend
  1047. backend ssh_backend
  1048. mode tcp
  1049. server ssh_server 127.0.0.1:22
  1050. EOF
  1051. echo -e "\n${C_GREEN}▶️ Reloading and starting HAProxy service...${C_RESET}"
  1052. systemctl daemon-reload
  1053. systemctl restart haproxy
  1054. sleep 2
  1055. if systemctl is-active --quiet haproxy; then
  1056. echo -e "\n${C_GREEN}✅ SUCCESS: SSL Tunnel is active.${C_RESET}"
  1057. echo -e "Clients can now connect to this server's IP on port ${C_YELLOW}${ssl_port}${C_RESET} using an SSL/TLS tunnel."
  1058. else
  1059. echo -e "\n${C_RED}❌ ERROR: HAProxy service failed to start.${C_RESET}"
  1060. echo -e "${C_YELLOW}ℹ️ Displaying HAProxy status for diagnostics:${C_RESET}"
  1061. systemctl status haproxy --no-pager
  1062. fi
  1063. }
  1064. uninstall_ssl_tunnel() {
  1065. echo -e "\n${C_BOLD}${C_PURPLE}--- 🗑️ Uninstalling SSL Tunnel ---${C_RESET}"
  1066. if ! command -v haproxy &> /dev/null; then
  1067. echo -e "${C_YELLOW}ℹ️ HAProxy not installed, skipping.${C_RESET}"
  1068. return
  1069. fi
  1070. echo -e "${C_GREEN}🛑 Stopping HAProxy service...${C_RESET}"
  1071. systemctl stop haproxy >/dev/null 2>&1
  1072. if [ -f "$HAPROXY_CONFIG" ]; then
  1073. echo -e "${C_GREEN}📝 Restoring default/empty HAProxy config...${C_RESET}"
  1074. cat > "$HAPROXY_CONFIG" <<-EOF
  1075. global
  1076. log /dev/log local0
  1077. log /dev/log local1 notice
  1078. defaults
  1079. log global
  1080. EOF
  1081. fi
  1082. if [ -f "$SSL_CERT_FILE" ]; then
  1083. local delete_cert="y"
  1084. if [[ "$UNINSTALL_MODE" != "silent" ]]; then
  1085. read -p "👉 Delete the SSL certificate at $SSL_CERT_FILE? (y/n): " delete_cert
  1086. fi
  1087. if [[ "$delete_cert" == "y" ]]; then
  1088. echo -e "${C_GREEN}🗑️ Removing SSL certificate...${C_RESET}"
  1089. rm -f "$SSL_CERT_FILE"
  1090. fi
  1091. fi
  1092. echo -e "${C_GREEN}✅ SSL Tunnel has been uninstalled.${C_RESET}"
  1093. }
  1094. show_dnstt_details() {
  1095. if [ -f "$DNSTT_CONFIG_FILE" ]; then
  1096. source "$DNSTT_CONFIG_FILE"
  1097. echo -e "\n${C_GREEN}=====================================================${C_RESET}"
  1098. echo -e "${C_GREEN} 📡 DNSTT Connection Details ${C_RESET}"
  1099. echo -e "${C_GREEN}=====================================================${C_RESET}"
  1100. echo -e "\n${C_WHITE}Your connection details:${C_RESET}"
  1101. echo -e " - ${C_CYAN}Tunnel Domain:${C_RESET} ${C_YELLOW}$TUNNEL_DOMAIN${C_RESET}"
  1102. echo -e " - ${C_CYAN}Public Key:${C_RESET} ${C_YELLOW}$PUBLIC_KEY${C_RESET}"
  1103. if [[ -n "$FORWARD_DESC" ]]; then
  1104. echo -e " - ${C_CYAN}Forwarding To:${C_RESET} ${C_YELLOW}$FORWARD_DESC${C_RESET}"
  1105. else
  1106. echo -e " - ${C_CYAN}Forwarding To:${C_RESET} ${C_YELLOW}Unknown (config_missing)${C_RESET}"
  1107. fi
  1108. if [[ -n "$MTU_VALUE" ]]; then
  1109. echo -e " - ${C_CYAN}MTU Value:${C_RESET} ${C_YELLOW}$MTU_VALUE${C_RESET}"
  1110. fi
  1111. if [[ "$DNSTT_RECORDS_MANAGED" == "false" && -n "$NS_DOMAIN" ]]; then
  1112. echo -e " - ${C_CYAN}NS Record:${C_RESET} ${C_YELLOW}$NS_DOMAIN${C_RESET}"
  1113. fi
  1114. if [[ "$FORWARD_DESC" == *"V2Ray"* ]]; then
  1115. echo -e " - ${C_CYAN}Action Required:${C_RESET} ${C_YELLOW}Ensure a V2Ray service (vless/vmess/trojan) listens on port 8787 (no TLS)${C_RESET}"
  1116. elif [[ "$FORWARD_DESC" == *"SSH"* ]]; then
  1117. echo -e " - ${C_CYAN}Action Required:${C_RESET} ${C_YELLOW}Ensure your SSH client is configured to use the DNS tunnel.${C_RESET}"
  1118. fi
  1119. echo -e "\n${C_DIM}Use these details in your client configuration.${C_RESET}"
  1120. else
  1121. echo -e "\n${C_YELLOW}ℹ️ DNSTT configuration file not found. Details are unavailable.${C_RESET}"
  1122. fi
  1123. }
  1124. install_dnstt() {
  1125. clear; show_banner
  1126. echo -e "${C_BOLD}${C_PURPLE}--- 📡 DNSTT (DNS Tunnel) Management ---${C_RESET}"
  1127. if [ -f "$DNSTT_SERVICE_FILE" ]; then
  1128. echo -e "\n${C_YELLOW}ℹ️ DNSTT is already installed.${C_RESET}"
  1129. show_dnstt_details
  1130. return
  1131. fi
  1132. # --- FIX: Force release of Port 53 / Disable systemd-resolved ---
  1133. echo -e "${C_GREEN}⚙️ Forcing release of Port 53 (stopping systemd-resolved)...${C_RESET}"
  1134. systemctl stop systemd-resolved >/dev/null 2>&1
  1135. systemctl disable systemd-resolved >/dev/null 2>&1
  1136. rm -f /etc/resolv.conf
  1137. echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null
  1138. # ----------------------------------------------------------------
  1139. echo -e "\n${C_BLUE}🔎 Checking if port 53 (UDP) is available...${C_RESET}"
  1140. if ss -lunp | grep -q ':53\s'; then
  1141. if [[ $(ps -p $(ss -lunp | grep ':53\s' | grep -oP 'pid=\K[0-9]+') -o comm=) == "systemd-resolve" ]]; then
  1142. echo -e "${C_YELLOW}⚠️ Warning: Port 53 is in use by 'systemd-resolved'.${C_RESET}"
  1143. echo -e "${C_YELLOW}This is the system's DNS stub resolver. It must be disabled to run DNSTT.${C_RESET}"
  1144. read -p "👉 Allow the script to automatically disable it and reconfigure DNS? (y/n): " resolve_confirm
  1145. if [[ "$resolve_confirm" == "y" || "$resolve_confirm" == "Y" ]]; then
  1146. echo -e "${C_GREEN}⚙️ Stopping and disabling systemd-resolved to free port 53...${C_RESET}"
  1147. systemctl stop systemd-resolved
  1148. systemctl disable systemd-resolved
  1149. chattr -i /etc/resolv.conf &>/dev/null
  1150. rm -f /etc/resolv.conf
  1151. echo "nameserver 8.8.8.8" > /etc/resolv.conf
  1152. chattr +i /etc/resolv.conf
  1153. echo -e "${C_GREEN}✅ Port 53 has been freed and DNS set to 8.8.8.8.${C_RESET}"
  1154. else
  1155. echo -e "${C_RED}❌ Cannot proceed without freeing port 53. Aborting.${C_RESET}"
  1156. return
  1157. fi
  1158. else
  1159. check_and_free_ports "53" || return
  1160. fi
  1161. else
  1162. echo -e "${C_GREEN}✅ Port 53 (UDP) is free to use.${C_RESET}"
  1163. fi
  1164. check_and_open_firewall_port 53 udp || return
  1165. local forward_port=""
  1166. local forward_desc=""
  1167. echo -e "\n${C_BLUE}Please choose where DNSTT should forward traffic:${C_RESET}"
  1168. echo -e " ${C_GREEN}[ 1]${C_RESET} ➡️ Forward to local SSH service (port 22)"
  1169. echo -e " ${C_GREEN}[ 2]${C_RESET} ➡️ Forward to local V2Ray backend (port 8787)"
  1170. read -p "👉 Enter your choice [2]: " fwd_choice
  1171. fwd_choice=${fwd_choice:-2}
  1172. if [[ "$fwd_choice" == "1" ]]; then
  1173. forward_port="22"
  1174. forward_desc="SSH (port 22)"
  1175. echo -e "${C_GREEN}ℹ️ DNSTT will forward to SSH on 127.0.0.1:22.${C_RESET}"
  1176. elif [[ "$fwd_choice" == "2" ]]; then
  1177. forward_port="8787"
  1178. forward_desc="V2Ray (port 8787)"
  1179. echo -e "${C_GREEN}ℹ️ DNSTT will forward to V2Ray on 127.0.0.1:8787.${C_RESET}"
  1180. else
  1181. echo -e "${C_RED}❌ Invalid choice. Aborting.${C_RESET}"
  1182. return
  1183. fi
  1184. local FORWARD_TARGET="127.0.0.1:$forward_port"
  1185. local NS_DOMAIN=""
  1186. local TUNNEL_DOMAIN=""
  1187. local DNSTT_RECORDS_MANAGED="true"
  1188. local NS_SUBDOMAIN=""
  1189. local TUNNEL_SUBDOMAIN=""
  1190. local HAS_IPV6="false"
  1191. read -p "👉 Auto-generate DNS records or use custom ones? (auto/custom) [auto]: " dns_choice
  1192. dns_choice=${dns_choice:-auto}
  1193. if [[ "$dns_choice" == "custom" ]]; then
  1194. DNSTT_RECORDS_MANAGED="false"
  1195. read -p "👉 Enter your full nameserver domain (e.g., ns1.yourdomain.com): " NS_DOMAIN
  1196. if [[ -z "$NS_DOMAIN" ]]; then echo -e "\n${C_RED}❌ Nameserver domain cannot be empty. Aborting.${C_RESET}"; return; fi
  1197. read -p "👉 Enter your full tunnel domain (e.g., tun.yourdomain.com): " TUNNEL_DOMAIN
  1198. if [[ -z "$TUNNEL_DOMAIN" ]]; then echo -e "\n${C_RED}❌ Tunnel domain cannot be empty. Aborting.${C_RESET}"; return; fi
  1199. else
  1200. echo -e "\n${C_BLUE}⚙️ Configuring DNS records for DNSTT...${C_RESET}"
  1201. local SERVER_IPV4
  1202. SERVER_IPV4=$(curl -s -4 icanhazip.com)
  1203. if ! _is_valid_ipv4 "$SERVER_IPV4"; then
  1204. echo -e "\n${C_RED}❌ Error: Could not retrieve a valid public IPv4 address from icanhazip.com.${C_RESET}"
  1205. echo -e "${C_YELLOW}ℹ️ Please check your server's network connection and DNS resolver settings.${C_RESET}"
  1206. echo -e " Output received: '$SERVER_IPV4'"
  1207. return 1
  1208. fi
  1209. local SERVER_IPV6
  1210. SERVER_IPV6=$(curl -s -6 icanhazip.com --max-time 5)
  1211. local RANDOM_STR
  1212. RANDOM_STR=$(head /dev/urandom | tr -dc a-z0-9 | head -c 6)
  1213. NS_SUBDOMAIN="ns-$RANDOM_STR"
  1214. TUNNEL_SUBDOMAIN="tun-$RANDOM_STR"
  1215. NS_DOMAIN="$NS_SUBDOMAIN.$DESEC_DOMAIN"
  1216. TUNNEL_DOMAIN="$TUNNEL_SUBDOMAIN.$DESEC_DOMAIN"
  1217. local API_DATA
  1218. API_DATA=$(printf '[{"subname": "%s", "type": "A", "ttl": 3600, "records": ["%s"]}, {"subname": "%s", "type": "NS", "ttl": 3600, "records": ["%s."]}]' \
  1219. "$NS_SUBDOMAIN" "$SERVER_IPV4" "$TUNNEL_SUBDOMAIN" "$NS_DOMAIN")
  1220. if [[ -n "$SERVER_IPV6" ]]; then
  1221. local aaaa_record
  1222. aaaa_record=$(printf ',{"subname": "%s", "type": "AAAA", "ttl": 3600, "records": ["%s"]}' "$NS_SUBDOMAIN" "$SERVER_IPV6")
  1223. API_DATA="${API_DATA%?}${aaaa_record}]"
  1224. HAS_IPV6="true"
  1225. fi
  1226. local CREATE_RESPONSE
  1227. CREATE_RESPONSE=$(curl -s -w "%{http_code}" -X POST "https://desec.io/api/v1/domains/$DESEC_DOMAIN/rrsets/" \
  1228. -H "Authorization: Token $DESEC_TOKEN" -H "Content-Type: application/json" \
  1229. --data "$API_DATA")
  1230. local HTTP_CODE=${CREATE_RESPONSE: -3}
  1231. local RESPONSE_BODY=${CREATE_RESPONSE:0:${#CREATE_RESPONSE}-3}
  1232. if [[ "$HTTP_CODE" -ne 201 ]]; then
  1233. echo -e "${C_RED}❌ Failed to create DNSTT records. API returned HTTP $HTTP_CODE.${C_RESET}"
  1234. echo "Response: $RESPONSE_BODY" | jq
  1235. return 1
  1236. fi
  1237. fi
  1238. read -p "👉 Enter MTU value (e.g., 512, 1200) or press [Enter] for default: " mtu_value
  1239. local mtu_string=""
  1240. if [[ "$mtu_value" =~ ^[0-9]+$ ]]; then
  1241. mtu_string=" -mtu $mtu_value"
  1242. echo -e "${C_GREEN}ℹ️ Using MTU: $mtu_value${C_RESET}"
  1243. else
  1244. mtu_value=""
  1245. echo -e "${C_YELLOW}ℹ️ Using default MTU.${C_RESET}"
  1246. fi
  1247. echo -e "\n${C_BLUE}📥 Downloading pre-compiled DNSTT server binary...${C_RESET}"
  1248. local arch
  1249. arch=$(uname -m)
  1250. local binary_url=""
  1251. if [[ "$arch" == "x86_64" ]]; then
  1252. binary_url="https://dnstt.network/dnstt-server-linux-amd64"
  1253. echo -e "${C_BLUE}ℹ️ Detected x86_64 (amd64) architecture.${C_RESET}"
  1254. elif [[ "$arch" == "aarch64" || "$arch" == "arm64" ]]; then
  1255. binary_url="https://dnstt.network/dnstt-server-linux-arm64"
  1256. echo -e "${C_BLUE}ℹ️ Detected ARM64 architecture.${C_RESET}"
  1257. else
  1258. echo -e "\n${C_RED}❌ Unsupported architecture: $arch. Cannot install DNSTT.${C_RESET}"
  1259. return
  1260. fi
  1261. curl -sL "$binary_url" -o "$DNSTT_BINARY"
  1262. if [ $? -ne 0 ]; then
  1263. echo -e "\n${C_RED}❌ Failed to download the DNSTT binary.${C_RESET}"
  1264. return
  1265. fi
  1266. chmod +x "$DNSTT_BINARY"
  1267. echo -e "${C_BLUE}🔐 Generating cryptographic keys...${C_RESET}"
  1268. mkdir -p "$DNSTT_KEYS_DIR"
  1269. "$DNSTT_BINARY" -gen-key -privkey-file "$DNSTT_KEYS_DIR/server.key" -pubkey-file "$DNSTT_KEYS_DIR/server.pub"
  1270. if [[ ! -f "$DNSTT_KEYS_DIR/server.key" ]]; then echo -e "${C_RED}❌ Failed to generate DNSTT keys.${C_RESET}"; return; fi
  1271. local PUBLIC_KEY
  1272. PUBLIC_KEY=$(cat "$DNSTT_KEYS_DIR/server.pub")
  1273. echo -e "\n${C_BLUE}📝 Creating systemd service...${C_RESET}"
  1274. cat > "$DNSTT_SERVICE_FILE" <<-EOF
  1275. [Unit]
  1276. Description=DNSTT (DNS Tunnel) Server for $forward_desc
  1277. After=network.target
  1278. [Service]
  1279. Type=simple
  1280. User=root
  1281. ExecStart=$DNSTT_BINARY -udp :53$mtu_string -privkey-file $DNSTT_KEYS_DIR/server.key $TUNNEL_DOMAIN $FORWARD_TARGET
  1282. Restart=always
  1283. RestartSec=3
  1284. [Install]
  1285. WantedBy=multi-user.target
  1286. EOF
  1287. echo -e "\n${C_BLUE}💾 Saving configuration and starting service...${C_RESET}"
  1288. cat > "$DNSTT_CONFIG_FILE" <<-EOF
  1289. NS_SUBDOMAIN="$NS_SUBDOMAIN"
  1290. TUNNEL_SUBDOMAIN="$TUNNEL_SUBDOMAIN"
  1291. NS_DOMAIN="$NS_DOMAIN"
  1292. TUNNEL_DOMAIN="$TUNNEL_DOMAIN"
  1293. PUBLIC_KEY="$PUBLIC_KEY"
  1294. FORWARD_DESC="$forward_desc"
  1295. DNSTT_RECORDS_MANAGED="$DNSTT_RECORDS_MANAGED"
  1296. HAS_IPV6="$HAS_IPV6"
  1297. MTU_VALUE="$mtu_value"
  1298. EOF
  1299. systemctl daemon-reload
  1300. systemctl enable dnstt.service
  1301. systemctl start dnstt.service
  1302. sleep 2
  1303. if systemctl is-active --quiet dnstt.service; then
  1304. echo -e "\n${C_GREEN}✅ SUCCESS: DNSTT has been installed and started!${C_RESET}"
  1305. show_dnstt_details
  1306. else
  1307. echo -e "\n${C_RED}❌ ERROR: DNSTT service failed to start.${C_RESET}"
  1308. journalctl -u dnstt.service -n 15 --no-pager
  1309. fi
  1310. }
  1311. uninstall_dnstt() {
  1312. echo -e "\n${C_BOLD}${C_PURPLE}--- 🗑️ Uninstalling DNSTT ---${C_RESET}"
  1313. if [ ! -f "$DNSTT_SERVICE_FILE" ]; then
  1314. echo -e "${C_YELLOW}ℹ️ DNSTT does not appear to be installed, skipping.${C_RESET}"
  1315. return
  1316. fi
  1317. local confirm="y"
  1318. if [[ "$UNINSTALL_MODE" != "silent" ]]; then
  1319. read -p "👉 Are you sure you want to uninstall DNSTT? This will delete DNS records if they were auto-generated. (y/n): " confirm
  1320. fi
  1321. if [[ "$confirm" != "y" ]]; then
  1322. echo -e "\n${C_YELLOW}❌ Uninstallation cancelled.${C_RESET}"
  1323. return
  1324. fi
  1325. echo -e "${C_BLUE}🛑 Stopping and disabling DNSTT service...${C_RESET}"
  1326. systemctl stop dnstt.service > /dev/null 2>&1
  1327. systemctl disable dnstt.service > /dev/null 2>&1
  1328. if [ -f "$DNSTT_CONFIG_FILE" ]; then
  1329. source "$DNSTT_CONFIG_FILE"
  1330. if [[ "$DNSTT_RECORDS_MANAGED" == "true" ]]; then
  1331. echo -e "${C_BLUE}🗑️ Removing auto-generated DNS records...${C_RESET}"
  1332. curl -s -X DELETE "https://desec.io/api/v1/domains/$DESEC_DOMAIN/rrsets/$TUNNEL_SUBDOMAIN/NS/" \
  1333. -H "Authorization: Token $DESEC_TOKEN" > /dev/null
  1334. curl -s -X DELETE "https://desec.io/api/v1/domains/$DESEC_DOMAIN/rrsets/$NS_SUBDOMAIN/A/" \
  1335. -H "Authorization: Token $DESEC_TOKEN" > /dev/null
  1336. if [[ "$HAS_IPV6" == "true" ]]; then
  1337. curl -s -X DELETE "https://desec.io/api/v1/domains/$DESEC_DOMAIN/rrsets/$NS_SUBDOMAIN/AAAA/" \
  1338. -H "Authorization: Token $DESEC_TOKEN" > /dev/null
  1339. fi
  1340. echo -e "${C_GREEN}✅ DNS records have been removed.${C_RESET}"
  1341. else
  1342. echo -e "${C_YELLOW}⚠️ DNS records were manually configured. Please delete them from your DNS provider.${C_RESET}"
  1343. fi
  1344. fi
  1345. echo -e "${C_BLUE}🗑️ Removing service files and binaries...${C_RESET}"
  1346. rm -f "$DNSTT_SERVICE_FILE"
  1347. rm -f "$DNSTT_BINARY"
  1348. rm -rf "$DNSTT_KEYS_DIR"
  1349. rm -f "$DNSTT_CONFIG_FILE"
  1350. systemctl daemon-reload
  1351. echo -e "${C_YELLOW}ℹ️ Making /etc/resolv.conf writable again...${C_RESET}"
  1352. chattr -i /etc/resolv.conf &>/dev/null
  1353. echo -e "\n${C_GREEN}✅ DNSTT has been successfully uninstalled.${C_RESET}"
  1354. }
  1355. install_falcon_proxy() {
  1356. clear; show_banner
  1357. echo -e "${C_BOLD}${C_PURPLE}--- 🦅 Installing Falcon Proxy (Websockets/Socks) ---${C_RESET}"
  1358. if [ -f "$FALCONPROXY_SERVICE_FILE" ]; then
  1359. echo -e "\n${C_YELLOW}ℹ️ Falcon Proxy is already installed.${C_RESET}"
  1360. if [ -f "$FALCONPROXY_CONFIG_FILE" ]; then
  1361. source "$FALCONPROXY_CONFIG_FILE"
  1362. echo -e " It is configured to run on port(s): ${C_YELLOW}$PORTS${C_RESET}"
  1363. echo -e " Installed Version: ${C_YELLOW}${INSTALLED_VERSION:-Unknown}${C_RESET}"
  1364. fi
  1365. read -p "👉 Do you want to reinstall/update? (y/n): " confirm_reinstall
  1366. if [[ "$confirm_reinstall" != "y" ]]; then return; fi
  1367. fi
  1368. echo -e "\n${C_BLUE}🌐 Fetching available versions from GitHub...${C_RESET}"
  1369. local releases_json=$(curl -s "https://api.github.com/repos/firewallfalcons/FirewallFalcon-Manager/releases")
  1370. if [[ -z "$releases_json" || "$releases_json" == "[]" ]]; then
  1371. echo -e "${C_RED}❌ Error: Could not fetch releases. Check internet or API limits.${C_RESET}"
  1372. return
  1373. fi
  1374. # Extract tag names
  1375. mapfile -t versions < <(echo "$releases_json" | jq -r '.[].tag_name')
  1376. if [ ${#versions[@]} -eq 0 ]; then
  1377. echo -e "${C_RED}❌ No releases found in the repository.${C_RESET}"
  1378. return
  1379. fi
  1380. echo -e "\n${C_CYAN}Select a version to install:${C_RESET}"
  1381. for i in "${!versions[@]}"; do
  1382. printf " ${C_GREEN}[%2d]${C_RESET} %s\n" "$((i+1))" "${versions[$i]}"
  1383. done
  1384. echo -e " ${C_RED} [ 0]${C_RESET} ↩️ Cancel"
  1385. local choice
  1386. while true; do
  1387. read -p "👉 Enter version number [1]: " choice
  1388. choice=${choice:-1}
  1389. if [[ "$choice" == "0" ]]; then return; fi
  1390. if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -le "${#versions[@]}" ]; then
  1391. SELECTED_VERSION="${versions[$((choice-1))]}"
  1392. break
  1393. else
  1394. echo -e "${C_RED}❌ Invalid selection.${C_RESET}"
  1395. fi
  1396. done
  1397. local ports
  1398. read -p "👉 Enter port(s) for Falcon Proxy (e.g., 8080 or 8080 8888) [8080]: " ports
  1399. ports=${ports:-8080}
  1400. local port_array=($ports)
  1401. for port in "${port_array[@]}"; do
  1402. if ! [[ "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
  1403. echo -e "\n${C_RED}❌ Invalid port number: $port. Aborting.${C_RESET}"
  1404. return
  1405. fi
  1406. check_and_free_ports "$port" || return
  1407. check_and_open_firewall_port "$port" tcp || return
  1408. done
  1409. echo -e "\n${C_GREEN}⚙️ Detecting system architecture...${C_RESET}"
  1410. local arch=$(uname -m)
  1411. local binary_name=""
  1412. if [[ "$arch" == "x86_64" ]]; then
  1413. binary_name="falconproxy"
  1414. echo -e "${C_BLUE}ℹ️ Detected x86_64 (amd64) architecture.${C_RESET}"
  1415. elif [[ "$arch" == "aarch64" || "$arch" == "arm64" ]]; then
  1416. binary_name="falconproxyarm"
  1417. echo -e "${C_BLUE}ℹ️ Detected ARM64 architecture.${C_RESET}"
  1418. else
  1419. echo -e "\n${C_RED}❌ Unsupported architecture: $arch. Cannot install Falcon Proxy.${C_RESET}"
  1420. return
  1421. fi
  1422. # Construct download URL based on selected version
  1423. local download_url="https://github.com/firewallfalcons/FirewallFalcon-Manager/releases/download/$SELECTED_VERSION/$binary_name"
  1424. echo -e "\n${C_GREEN}📥 Downloading Falcon Proxy $SELECTED_VERSION ($binary_name)...${C_RESET}"
  1425. wget -q --show-progress -O "$FALCONPROXY_BINARY" "$download_url"
  1426. if [ $? -ne 0 ]; then
  1427. echo -e "\n${C_RED}❌ Failed to download the binary. Please ensure version $SELECTED_VERSION has asset '$binary_name'.${C_RESET}"
  1428. return
  1429. fi
  1430. chmod +x "$FALCONPROXY_BINARY"
  1431. echo -e "\n${C_GREEN}📝 Creating systemd service file...${C_RESET}"
  1432. cat > "$FALCONPROXY_SERVICE_FILE" <<EOF
  1433. [Unit]
  1434. Description=Falcon Proxy ($SELECTED_VERSION)
  1435. After=network.target
  1436. [Service]
  1437. User=root
  1438. Type=simple
  1439. ExecStart=$FALCONPROXY_BINARY -p $ports
  1440. Restart=always
  1441. RestartSec=2s
  1442. [Install]
  1443. WantedBy=default.target
  1444. EOF
  1445. echo -e "\n${C_GREEN}💾 Saving configuration...${C_RESET}"
  1446. cat > "$FALCONPROXY_CONFIG_FILE" <<EOF
  1447. PORTS="$ports"
  1448. INSTALLED_VERSION="$SELECTED_VERSION"
  1449. EOF
  1450. echo -e "\n${C_GREEN}▶️ Enabling and starting Falcon Proxy service...${C_RESET}"
  1451. systemctl daemon-reload
  1452. systemctl enable falconproxy.service
  1453. systemctl restart falconproxy.service
  1454. sleep 2
  1455. if systemctl is-active --quiet falconproxy; then
  1456. echo -e "\n${C_GREEN}✅ SUCCESS: Falcon Proxy $SELECTED_VERSION is installed and active.${C_RESET}"
  1457. echo -e " Listening on port(s): ${C_YELLOW}$ports${C_RESET}"
  1458. else
  1459. echo -e "\n${C_RED}❌ ERROR: Falcon Proxy service failed to start.${C_RESET}"
  1460. echo -e "${C_YELLOW}ℹ️ Displaying last 15 lines of the service log for diagnostics:${C_RESET}"
  1461. journalctl -u falconproxy.service -n 15 --no-pager
  1462. fi
  1463. }
  1464. uninstall_falcon_proxy() {
  1465. echo -e "\n${C_BOLD}${C_PURPLE}--- 🗑️ Uninstalling Falcon Proxy ---${C_RESET}"
  1466. if [ ! -f "$FALCONPROXY_SERVICE_FILE" ]; then
  1467. echo -e "${C_YELLOW}ℹ️ Falcon Proxy is not installed, skipping.${C_RESET}"
  1468. return
  1469. fi
  1470. echo -e "${C_GREEN}🛑 Stopping and disabling Falcon Proxy service...${C_RESET}"
  1471. systemctl stop falconproxy.service >/dev/null 2>&1
  1472. systemctl disable falconproxy.service >/dev/null 2>&1
  1473. echo -e "${C_GREEN}🗑️ Removing service file...${C_RESET}"
  1474. rm -f "$FALCONPROXY_SERVICE_FILE"
  1475. systemctl daemon-reload
  1476. echo -e "${C_GREEN}🗑️ Removing binary and config files...${C_RESET}"
  1477. rm -f "$FALCONPROXY_BINARY"
  1478. rm -f "$FALCONPROXY_CONFIG_FILE"
  1479. echo -e "${C_GREEN}✅ Falcon Proxy has been uninstalled successfully.${C_RESET}"
  1480. }
  1481. # --- ZiVPN Installation Logic ---
  1482. install_zivpn() {
  1483. clear; show_banner
  1484. echo -e "${C_BOLD}${C_PURPLE}--- 🚀 Installing ZiVPN (UDP/VPN) ---${C_RESET}"
  1485. if [ -f "$ZIVPN_SERVICE_FILE" ]; then
  1486. echo -e "\n${C_YELLOW}ℹ️ ZiVPN is already installed.${C_RESET}"
  1487. return
  1488. fi
  1489. echo -e "\n${C_GREEN}⚙️ Checking system architecture...${C_RESET}"
  1490. local arch=$(uname -m)
  1491. local zivpn_url=""
  1492. if [[ "$arch" == "x86_64" ]]; then
  1493. zivpn_url="https://github.com/zahidbd2/udp-zivpn/releases/download/udp-zivpn_1.4.9/udp-zivpn-linux-amd64"
  1494. echo -e "${C_BLUE}ℹ️ Detected AMD64/x86_64 architecture.${C_RESET}"
  1495. elif [[ "$arch" == "aarch64" ]]; then
  1496. zivpn_url="https://github.com/zahidbd2/udp-zivpn/releases/download/udp-zivpn_1.4.9/udp-zivpn-linux-arm64"
  1497. echo -e "${C_BLUE}ℹ️ Detected ARM64 architecture.${C_RESET}"
  1498. elif [[ "$arch" == "armv7l" || "$arch" == "arm" ]]; then
  1499. zivpn_url="https://github.com/zahidbd2/udp-zivpn/releases/download/udp-zivpn_1.4.9/udp-zivpn-linux-arm"
  1500. echo -e "${C_BLUE}ℹ️ Detected ARM architecture.${C_RESET}"
  1501. else
  1502. echo -e "${C_RED}❌ Unsupported architecture: $arch${C_RESET}"
  1503. return
  1504. fi
  1505. echo -e "\n${C_GREEN}📦 Downloading ZiVPN binary...${C_RESET}"
  1506. if ! wget -q --show-progress -O "$ZIVPN_BIN" "$zivpn_url"; then
  1507. echo -e "${C_RED}❌ Download failed. Check internet connection.${C_RESET}"
  1508. return
  1509. fi
  1510. chmod +x "$ZIVPN_BIN"
  1511. echo -e "\n${C_GREEN}⚙️ Configuring ZIVPN...${C_RESET}"
  1512. mkdir -p "$ZIVPN_DIR"
  1513. # Generate Certificates
  1514. echo -e "${C_BLUE}🔐 Generating self-signed certificates...${C_RESET}"
  1515. if ! command -v openssl &>/dev/null; then apt-get install -y openssl &>/dev/null; fi
  1516. openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
  1517. -subj "/C=US/ST=California/L=Los Angeles/O=Example Corp/OU=IT Department/CN=zivpn" \
  1518. -keyout "$ZIVPN_KEY_FILE" -out "$ZIVPN_CERT_FILE" 2>/dev/null
  1519. if [ ! -f "$ZIVPN_CERT_FILE" ]; then
  1520. echo -e "${C_RED}❌ Failed to generate certificates.${C_RESET}"
  1521. return
  1522. fi
  1523. # System Tuning
  1524. echo -e "${C_BLUE}🔧 Tuning system network parameters...${C_RESET}"
  1525. sysctl -w net.core.rmem_max=16777216 >/dev/null
  1526. sysctl -w net.core.wmem_max=16777216 >/dev/null
  1527. # Create Service
  1528. echo -e "${C_BLUE}📝 Creating systemd service file...${C_RESET}"
  1529. cat <<EOF > "$ZIVPN_SERVICE_FILE"
  1530. [Unit]
  1531. Description=zivpn VPN Server
  1532. After=network.target
  1533. [Service]
  1534. Type=simple
  1535. User=root
  1536. WorkingDirectory=$ZIVPN_DIR
  1537. ExecStart=$ZIVPN_BIN server -c $ZIVPN_CONFIG_FILE
  1538. Restart=always
  1539. RestartSec=3
  1540. Environment=ZIVPN_LOG_LEVEL=info
  1541. CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
  1542. AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
  1543. NoNewPrivileges=true
  1544. [Install]
  1545. WantedBy=multi-user.target
  1546. EOF
  1547. # Configure Passwords
  1548. echo -e "\n${C_YELLOW}🔑 ZiVPN Password Setup${C_RESET}"
  1549. read -p "👉 Enter passwords separated by commas (e.g., user1,user2) [Default: 'zi']: " input_config
  1550. if [ -n "$input_config" ]; then
  1551. IFS=',' read -r -a config_array <<< "$input_config"
  1552. # Ensure array format for JSON
  1553. json_passwords=$(printf '"%s",' "${config_array[@]}")
  1554. json_passwords="[${json_passwords%,}]"
  1555. else
  1556. json_passwords='["zi"]'
  1557. fi
  1558. # Create Config File
  1559. cat <<EOF > "$ZIVPN_CONFIG_FILE"
  1560. {
  1561. "listen": ":5667",
  1562. "cert": "$ZIVPN_CERT_FILE",
  1563. "key": "$ZIVPN_KEY_FILE",
  1564. "obfs":"zivpn",
  1565. "auth": {
  1566. "mode": "passwords",
  1567. "config": $json_passwords
  1568. }
  1569. }
  1570. EOF
  1571. echo -e "\n${C_GREEN}🚀 Starting ZiVPN Service...${C_RESET}"
  1572. systemctl daemon-reload
  1573. systemctl enable zivpn.service
  1574. systemctl start zivpn.service
  1575. # Port Forwarding / Firewall
  1576. echo -e "${C_BLUE}🔥 Configuring Firewall Rules (Redirecting 6000-19999 -> 5667)...${C_RESET}"
  1577. # Determine primary interface
  1578. local iface=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)
  1579. if [ -n "$iface" ]; then
  1580. iptables -t nat -A PREROUTING -i "$iface" -p udp --dport 6000:19999 -j DNAT --to-destination :5667
  1581. # Note: IPTables rules are not persistent by default without iptables-persistent package
  1582. else
  1583. echo -e "${C_YELLOW}⚠️ Could not detect default interface for IPTables redirection.${C_RESET}"
  1584. fi
  1585. if command -v ufw &>/dev/null; then
  1586. ufw allow 6000:19999/udp >/dev/null
  1587. ufw allow 5667/udp >/dev/null
  1588. fi
  1589. # Cleanup
  1590. rm -f zi.sh zi2.sh 2>/dev/null
  1591. if systemctl is-active --quiet zivpn.service; then
  1592. echo -e "\n${C_GREEN}✅ ZiVPN Installed Successfully!${C_RESET}"
  1593. echo -e " - UDP Port: 5667 (Direct)"
  1594. echo -e " - UDP Ports: 6000-19999 (Forwarded)"
  1595. else
  1596. echo -e "\n${C_RED}❌ ZiVPN Service failed to start. Check logs: journalctl -u zivpn.service${C_RESET}"
  1597. fi
  1598. }
  1599. uninstall_zivpn() {
  1600. clear; show_banner
  1601. echo -e "${C_BOLD}${C_PURPLE}--- 🗑️ Uninstall ZiVPN ---${C_RESET}"
  1602. if [ ! -f "$ZIVPN_SERVICE_FILE" ] && [ ! -f "$ZIVPN_BIN" ]; then
  1603. echo -e "\n${C_YELLOW}ℹ️ ZiVPN does not appear to be installed.${C_RESET}"
  1604. return
  1605. fi
  1606. read -p "👉 Are you sure you want to uninstall ZiVPN? (y/n): " confirm
  1607. if [[ "$confirm" != "y" ]]; then echo -e "${C_YELLOW}Cancelled.${C_RESET}"; return; fi
  1608. echo -e "\n${C_BLUE}🛑 Stopping services...${C_RESET}"
  1609. systemctl stop zivpn.service 2>/dev/null
  1610. systemctl disable zivpn.service 2>/dev/null
  1611. echo -e "${C_BLUE}🗑️ Removing files...${C_RESET}"
  1612. rm -f "$ZIVPN_SERVICE_FILE"
  1613. rm -rf "$ZIVPN_DIR"
  1614. rm -f "$ZIVPN_BIN"
  1615. systemctl daemon-reload
  1616. # Clean cache (from original uninstall script logic)
  1617. echo -e "${C_BLUE}🧹 Cleaning memory cache...${C_RESET}"
  1618. sync; echo 3 > /proc/sys/vm/drop_caches
  1619. echo -e "\n${C_GREEN}✅ ZiVPN Uninstalled Successfully.${C_RESET}"
  1620. }
  1621. purge_nginx() {
  1622. local mode="$1"
  1623. if [[ "$mode" != "silent" ]]; then
  1624. clear; show_banner
  1625. echo -e "${C_BOLD}${C_PURPLE}--- 🔥 Purge Nginx Installation ---${C_RESET}"
  1626. if ! command -v nginx &> /dev/null; then
  1627. echo -e "\n${C_YELLOW}ℹ️ Nginx is not installed. Nothing to do.${C_RESET}"
  1628. return
  1629. fi
  1630. read -p "👉 This will COMPLETELY REMOVE Nginx and all its configuration files. Are you sure? (y/n): " confirm
  1631. if [[ "$confirm" != "y" ]]; then
  1632. echo -e "\n${C_YELLOW}❌ Uninstallation cancelled.${C_RESET}"
  1633. return
  1634. fi
  1635. fi
  1636. echo -e "\n${C_BLUE}🛑 Stopping Nginx service...${C_RESET}"
  1637. systemctl stop nginx >/dev/null 2>&1
  1638. echo -e "\n${C_BLUE}🗑️ Purging Nginx packages...${C_RESET}"
  1639. apt-get purge -y nginx nginx-common >/dev/null 2>&1
  1640. apt-get autoremove -y >/dev/null 2>&1
  1641. echo -e "\n${C_BLUE}🗑️ Removing leftover files...${C_RESET}"
  1642. rm -f /etc/ssl/certs/nginx-selfsigned.pem
  1643. rm -f /etc/ssl/private/nginx-selfsigned.key
  1644. rm -rf /etc/nginx
  1645. rm -f "${NGINX_CONFIG_FILE}.bak"
  1646. rm -f "${NGINX_CONFIG_FILE}.bak.certbot"
  1647. rm -f "${NGINX_CONFIG_FILE}.bak.selfsigned"
  1648. if [[ "$mode" != "silent" ]]; then
  1649. echo -e "\n${C_GREEN}✅ Nginx has been completely purged from the system.${C_RESET}"
  1650. fi
  1651. }
  1652. install_nginx_proxy() {
  1653. clear; show_banner
  1654. echo -e "${C_BOLD}${C_PURPLE}--- 🚀 Installing Nginx Main Proxy (Ports 80 & 443) ---${C_RESET}"
  1655. if command -v nginx &> /dev/null; then
  1656. echo -e "\n${C_YELLOW}⚠️ An existing Nginx installation was found.${C_RESET}"
  1657. read -p "👉 To ensure a clean setup, the existing Nginx will be purged. Continue? (y/n): " confirm_purge
  1658. if [[ "$confirm_purge" != "y" ]]; then
  1659. echo -e "\n${C_RED}❌ Installation cancelled.${C_RESET}"
  1660. return
  1661. fi
  1662. purge_nginx "silent"
  1663. fi
  1664. echo -e "\n${C_BLUE}📦 Installing Nginx package...${C_RESET}"
  1665. apt-get update && apt-get install -y nginx || { echo -e "${C_RED}❌ Failed to install Nginx.${C_RESET}"; return; }
  1666. check_and_free_ports "80" "443" || return
  1667. # --- Custom Port Selection ---
  1668. local tls_ports
  1669. read -p "👉 Enter TLS/SSL Port(s) [Default: 443]: " input_tls
  1670. if [[ -z "$input_tls" ]]; then tls_ports="443"; else tls_ports="$input_tls"; fi
  1671. local http_ports
  1672. read -p "👉 Enter HTTP/Non-TLS Port(s) [Default: 80]: " input_http
  1673. if [[ -z "$input_http" ]]; then http_ports="80"; else http_ports="$input_http"; fi
  1674. # Convert to arrays
  1675. read -a tls_ports_array <<< "$tls_ports"
  1676. read -a http_ports_array <<< "$http_ports"
  1677. # Process Ports: Free and Open
  1678. for port in "${tls_ports_array[@]}" "${http_ports_array[@]}"; do
  1679. if ! [[ "$port" =~ ^[0-9]+$ ]]; then echo -e "${C_RED}❌ Invalid port: $port${C_RESET}"; return; fi
  1680. check_and_free_ports "$port" || return
  1681. check_and_open_firewall_port "$port" tcp || return
  1682. done
  1683. echo -e "\n${C_GREEN}🔐 Generating self-signed SSL certificate for Nginx...${C_RESET}"
  1684. local SSL_CERT="/etc/ssl/certs/nginx-selfsigned.pem"
  1685. local SSL_KEY="/etc/ssl/private/nginx-selfsigned.key"
  1686. mkdir -p /etc/ssl/certs /etc/ssl/private
  1687. openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
  1688. -keyout "$SSL_KEY" \
  1689. -out "$SSL_CERT" \
  1690. -subj "/CN=firewallfalcon.proxy" >/dev/null 2>&1 || { echo -e "${C_RED}❌ Failed to generate SSL certificate.${C_RESET}"; return; }
  1691. echo -e "\n${C_GREEN}📝 Applying Nginx reverse proxy configuration...${C_RESET}"
  1692. mv "$NGINX_CONFIG_FILE" "${NGINX_CONFIG_FILE}.bak" 2>/dev/null
  1693. # --- Generate Listen Directives ---
  1694. local listen_block=""
  1695. for port in "${http_ports_array[@]}"; do
  1696. listen_block="${listen_block} listen $port;\n listen [::]:$port;\n"
  1697. done
  1698. for port in "${tls_ports_array[@]}"; do
  1699. listen_block="${listen_block} listen $port ssl http2;\n listen [::]:$port ssl http2;\n"
  1700. done
  1701. cat > "$NGINX_CONFIG_FILE" <<EOF
  1702. server {
  1703. server_tokens off;
  1704. server_name _;
  1705. $(echo -e "$listen_block")
  1706. ssl_certificate /etc/ssl/certs/nginx-selfsigned.pem;
  1707. ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
  1708. ssl_protocols TLSv1.2 TLSv1.3;
  1709. ssl_ciphers HIGH:!aNULL:!eNULL:!MD5:!DES:!RC4:!ADH!SSLv3:!EXP!PSK!DSS;
  1710. resolver 8.8.8.8;
  1711. location ~ ^/(?<fwdport>\d+)/(?<fwdpath>.*)$ {
  1712. client_max_body_size 0;
  1713. client_body_timeout 1d;
  1714. grpc_read_timeout 1d;
  1715. grpc_socket_keepalive on;
  1716. proxy_read_timeout 1d;
  1717. proxy_http_version 1.1;
  1718. proxy_buffering off;
  1719. proxy_request_buffering off;
  1720. proxy_socket_keepalive on;
  1721. proxy_set_header Upgrade \$http_upgrade;
  1722. proxy_set_header Connection "upgrade";
  1723. proxy_set_header Host \$host;
  1724. proxy_set_header X-Real-IP \$remote_addr;
  1725. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  1726. if (\$content_type ~* "GRPC") { grpc_pass grpc://127.0.0.1:\$fwdport\$is_args\$args; break; }
  1727. proxy_pass http://127.0.0.1:\$fwdport\$is_args\$args;
  1728. break;
  1729. }
  1730. location / {
  1731. proxy_read_timeout 3600s;
  1732. proxy_buffering off;
  1733. proxy_request_buffering off;
  1734. proxy_http_version 1.1;
  1735. proxy_socket_keepalive on;
  1736. tcp_nodelay on;
  1737. tcp_nopush off;
  1738. proxy_pass http://127.0.0.1:8080;
  1739. proxy_set_header Upgrade \$http_upgrade;
  1740. proxy_set_header Connection "upgrade";
  1741. proxy_set_header Host \$host;
  1742. proxy_set_header X-Real-IP \$remote_addr;
  1743. proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
  1744. }
  1745. }
  1746. EOF
  1747. echo -e "\n${C_GREEN}▶️ Restarting Nginx service...${C_RESET}"
  1748. systemctl restart nginx
  1749. sleep 2
  1750. if systemctl is-active --quiet nginx; then
  1751. echo -e "\n${C_GREEN}✅ SUCCESS: Nginx Reverse Proxy is active.${C_RESET}"
  1752. echo -e " - TLS Ports: ${C_YELLOW}${tls_ports}${C_RESET}"
  1753. echo -e " - HTTP Ports: ${C_YELLOW}${http_ports}${C_RESET}"
  1754. # Save ports for future reference
  1755. echo "TLS_PORTS=\"$tls_ports\"" > "$NGINX_PORTS_FILE"
  1756. echo "HTTP_PORTS=\"$http_ports\"" >> "$NGINX_PORTS_FILE"
  1757. else
  1758. echo -e "\n${C_RED}❌ ERROR: Nginx service failed to start.${C_RESET}"
  1759. echo -e "${C_YELLOW}ℹ️ Displaying Nginx status for diagnostics:${C_RESET}"
  1760. systemctl status nginx --no-pager
  1761. echo -e "${C_YELLOW}🔄 Restoring previous Nginx config...${C_RESET}"
  1762. mv "${NGINX_CONFIG_FILE}.bak" "$NGINX_CONFIG_FILE" 2>/dev/null
  1763. fi
  1764. }
  1765. _install_certbot() {
  1766. if command -v certbot &> /dev/null; then
  1767. echo -e "${C_GREEN}✅ Certbot is already installed.${C_RESET}"
  1768. return 0
  1769. fi
  1770. echo -e "${C_YELLOW}⚠️ Certbot (for SSL) is not found.${C_RESET}"
  1771. read -p "👉 Do you want to install Certbot now? (y/n): " confirm_install
  1772. if [[ "$confirm_install" != "y" ]]; then
  1773. echo -e "${C_RED}❌ Installation skipped. Cannot proceed.${C_RESET}"
  1774. return 1
  1775. fi
  1776. echo -e "${C_BLUE}📦 Installing Certbot...${C_RESET}"
  1777. apt-get update > /dev/null 2>&1
  1778. apt-get install -y certbot || {
  1779. echo -e "${C_RED}❌ Failed to install Certbot.${C_RESET}"
  1780. return 1
  1781. }
  1782. echo -e "${C_GREEN}✅ Certbot installed successfully.${C_RESET}"
  1783. return 0
  1784. }
  1785. request_certbot_ssl() {
  1786. clear; show_banner
  1787. echo -e "${C_BOLD}${C_PURPLE}--- 🔒 Request Let's Encrypt SSL (Certbot) ---${C_RESET}"
  1788. if ! systemctl is-active --quiet nginx; then
  1789. echo -e "\n${C_RED}❌ Nginx is not running. Please ensure Nginx is installed and active.${C_RESET}"
  1790. return
  1791. fi
  1792. _install_certbot || return
  1793. echo
  1794. read -p "👉 Enter your domain name (e.g., vps.example.com): " domain_name
  1795. if [[ -z "$domain_name" ]]; then
  1796. echo -e "\n${C_RED}❌ Domain name cannot be empty. Aborting.${C_RESET}"
  1797. return
  1798. fi
  1799. read -p "👉 Enter your email address (for Let's Encrypt): " email
  1800. if [[ -z "$email" ]]; then
  1801. echo -e "\n${C_RED}❌ Email address cannot be empty. Aborting.${C_RESET}"
  1802. return
  1803. fi
  1804. echo -e "\n${C_BLUE}🛑 Stopping Nginx temporarily for validation...${C_RESET}"
  1805. systemctl stop nginx
  1806. sleep 2
  1807. if ss -lntp | grep -q ":80\s"; then
  1808. echo -e "${C_RED}❌ Failed to free port 80, another process might be using it. Aborting.${C_RESET}"
  1809. systemctl start nginx
  1810. return
  1811. fi
  1812. echo -e "\n${C_BLUE}🚀 Requesting certificate for ${C_YELLOW}$domain_name...${C_RESET}"
  1813. certbot certonly --standalone -d "$domain_name" --non-interactive --agree-tos -m "$email"
  1814. if [ $? -ne 0 ]; then
  1815. echo -e "\n${C_RED}❌ Certbot failed to obtain a certificate.${C_RESET}"
  1816. echo -e "${C_YELLOW}ℹ️ Please check your domain's DNS 'A' record points to this server's IP.${C_RESET}"
  1817. systemctl start nginx
  1818. return
  1819. fi
  1820. local SSL_CERT_LIVE="/etc/letsencrypt/live/$domain_name/fullchain.pem"
  1821. local SSL_KEY_LIVE="/etc/letsencrypt/live/$domain_name/privkey.pem"
  1822. if [ ! -f "$SSL_CERT_LIVE" ] || [ ! -f "$SSL_KEY_LIVE" ]; then
  1823. echo -e "\n${C_RED}❌ Certbot succeeded, but cert files not found at expected location.${C_RESET}"
  1824. systemctl start nginx
  1825. return
  1826. fi
  1827. echo -e "\n${C_GREEN}✅ Certificate obtained successfully!${C_RESET}"
  1828. echo -e "${C_BLUE}📝 Updating Nginx configuration...${C_RESET}"
  1829. cp "$NGINX_CONFIG_FILE" "${NGINX_CONFIG_FILE}.bak.selfsigned"
  1830. sed -i "s|server_name _;|server_name $domain_name;|" "$NGINX_CONFIG_FILE"
  1831. sed -i "s|ssl_certificate /etc/ssl/certs/nginx-selfsigned.pem;|ssl_certificate $SSL_CERT_LIVE;|" "$NGINX_CONFIG_FILE"
  1832. sed -i "s|ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;|ssl_certificate_key $SSL_KEY_LIVE;|" "$NGINX_CONFIG_FILE"
  1833. echo -e "\n${C_BLUE}▶️ Restarting Nginx with new certificate...${C_RESET}"
  1834. systemctl start nginx
  1835. sleep 2
  1836. if systemctl is-active --quiet nginx; then
  1837. echo -e "\n${C_GREEN}✅ SUCCESS: Nginx is active with your new Let's Encrypt certificate!${C_RESET}"
  1838. else
  1839. echo -e "\n${C_RED}❌ ERROR: Nginx failed to start with the new certificate.${C_RESET}"
  1840. echo -e "${C_YELLOW}🔄 Restoring self-signed certificate config...${C_RESET}"
  1841. mv "${NGINX_CONFIG_FILE}.bak.selfsigned" "$NGINX_CONFIG_FILE"
  1842. systemctl restart nginx
  1843. fi
  1844. }
  1845. nginx_proxy_menu() {
  1846. clear; show_banner
  1847. echo -e "${C_BOLD}${C_PURPLE}--- 🌐 Nginx Main Proxy Management ---${C_RESET}"
  1848. local active_status="${C_STATUS_I}Inactive${C_RESET}"
  1849. if systemctl is-active --quiet nginx; then
  1850. active_status="${C_STATUS_A}Active${C_RESET}"
  1851. fi
  1852. # Retrieve Ports Info
  1853. local ports_info=""
  1854. if [ -f "$NGINX_PORTS_FILE" ]; then
  1855. source "$NGINX_PORTS_FILE"
  1856. ports_info="\n ${C_DIM}TLS: $TLS_PORTS | HTTP: $HTTP_PORTS${C_RESET}"
  1857. fi
  1858. echo -e "\n${C_WHITE}Current Status: ${active_status}${ports_info}"
  1859. echo -e "\n${C_BOLD}Select an action:${C_RESET}\n"
  1860. if systemctl is-active --quiet nginx; then
  1861. printf " ${C_CHOICE}[ 1]${C_RESET} %-40s\n" "🛑 Stop Nginx Service"
  1862. printf " ${C_CHOICE}[ 2]${C_RESET} %-40s\n" "🔄 Restart Nginx Service"
  1863. printf " ${C_CHOICE}[ 3]${C_RESET} %-40s\n" "⚙️ Re-install/Re-configure (Change Ports)"
  1864. printf " ${C_CHOICE}[ 4]${C_RESET} %-40s\n" "🔒 Request/Renew SSL (Certbot)"
  1865. printf " ${C_CHOICE}[ 5]${C_RESET} %-40s\n" "🔥 Uninstall/Purge Nginx"
  1866. else
  1867. printf " ${C_CHOICE}[ 1]${C_RESET} %-40s\n" "▶️ Start Nginx Service"
  1868. printf " ${C_CHOICE}[ 3]${C_RESET} %-40s\n" "⚙️ Install/Configure Nginx"
  1869. printf " ${C_CHOICE}[ 5]${C_RESET} %-40s\n" "🔥 Uninstall/Purge Nginx"
  1870. fi
  1871. echo -e "\n ${C_WARN}[ 0]${C_RESET} ↩️ Return to previous menu"
  1872. echo
  1873. read -p "👉 Enter your choice: " choice
  1874. case $choice in
  1875. 1)
  1876. if systemctl is-active --quiet nginx; then
  1877. echo -e "\n${C_BLUE}🛑 Stopping Nginx...${C_RESET}"
  1878. systemctl stop nginx
  1879. echo -e "${C_GREEN}✅ Nginx stopped.${C_RESET}"
  1880. else
  1881. echo -e "\n${C_BLUE}▶️ Starting Nginx...${C_RESET}"
  1882. systemctl start nginx
  1883. if systemctl is-active --quiet nginx; then echo -e "${C_GREEN}✅ Nginx Started.${C_RESET}"; else echo -e "${C_RED}❌ Failed to start.${C_RESET}"; fi
  1884. fi
  1885. press_enter
  1886. ;;
  1887. 2)
  1888. echo -e "\n${C_BLUE}🔄 Restarting Nginx...${C_RESET}"
  1889. systemctl restart nginx
  1890. press_enter
  1891. ;;
  1892. 3)
  1893. install_nginx_proxy; press_enter
  1894. ;;
  1895. 4)
  1896. request_certbot_ssl; press_enter
  1897. ;;
  1898. 5)
  1899. purge_nginx; press_enter
  1900. ;;
  1901. 0) return ;;
  1902. *) invalid_option ;;
  1903. esac
  1904. }
  1905. install_xui_panel() {
  1906. clear; show_banner
  1907. echo -e "${C_BOLD}${C_PURPLE}--- 🚀 Install X-UI Panel ---${C_RESET}"
  1908. echo -e "\nThis will download and run the official installation script for X-UI."
  1909. echo -e "Choose an installation option:\n"
  1910. echo -e "Choose an installation option:\n"
  1911. printf " ${C_GREEN}[ 1]${C_RESET} %-40s\n" "Install the latest version of X-UI"
  1912. printf " ${C_GREEN}[ 2]${C_RESET} %-40s\n" "Install a specific version of X-UI"
  1913. echo -e "\n ${C_RED}[ 0]${C_RESET} ❌ Cancel Installation"
  1914. echo
  1915. read -p "👉 Select an option: " choice
  1916. case $choice in
  1917. 1)
  1918. echo -e "\n${C_BLUE}⚙️ Installing the latest version...${C_RESET}"
  1919. bash <(curl -Ls https://raw.githubusercontent.com/alireza0/x-ui/master/install.sh)
  1920. ;;
  1921. 2)
  1922. read -p "👉 Enter the version to install (e.g., 1.8.0): " version
  1923. if [[ -z "$version" ]]; then
  1924. echo -e "\n${C_RED}❌ Version number cannot be empty.${C_RESET}"
  1925. return
  1926. fi
  1927. echo -e "\n${C_BLUE}⚙️ Installing version ${C_YELLOW}$version...${C_RESET}"
  1928. VERSION=$version bash <(curl -Ls "https://raw.githubusercontent.com/alireza0/x-ui/$version/install.sh") "$version"
  1929. ;;
  1930. 0)
  1931. echo -e "\n${C_YELLOW}❌ Installation cancelled.${C_RESET}"
  1932. ;;
  1933. *)
  1934. echo -e "\n${C_RED}❌ Invalid option.${C_RESET}"
  1935. ;;
  1936. esac
  1937. }
  1938. uninstall_xui_panel() {
  1939. clear; show_banner
  1940. echo -e "${C_BOLD}${C_PURPLE}--- 🗑️ Uninstall X-UI Panel ---${C_RESET}"
  1941. if ! command -v x-ui &> /dev/null; then
  1942. echo -e "\n${C_YELLOW}ℹ️ X-UI does not appear to be installed.${C_RESET}"
  1943. return
  1944. fi
  1945. read -p "👉 Are you sure you want to thoroughly uninstall X-UI? (y/n): " confirm
  1946. if [[ "$confirm" == "y" ]]; then
  1947. echo -e "\n${C_BLUE}⚙️ Running the default X-UI uninstaller first...${C_RESET}"
  1948. x-ui uninstall >/dev/null 2>&1
  1949. echo -e "\n${C_BLUE}🧹 Performing a full cleanup to ensure complete removal...${C_RESET}"
  1950. echo " - Stopping and disabling x-ui service..."
  1951. systemctl stop x-ui >/dev/null 2>&1
  1952. systemctl disable x-ui >/dev/null 2>&1
  1953. echo " - Removing x-ui files and directories..."
  1954. rm -f /etc/systemd/system/x-ui.service
  1955. rm -f /usr/local/bin/x-ui
  1956. rm -rf /usr/local/x-ui/
  1957. rm -rf /etc/x-ui/
  1958. echo " - Reloading systemd daemon..."
  1959. systemctl daemon-reload
  1960. echo -e "\n${C_GREEN}✅ X-UI has been thoroughly uninstalled.${C_RESET}"
  1961. else
  1962. echo -e "\n${C_YELLOW}❌ Uninstallation cancelled.${C_RESET}"
  1963. fi
  1964. }
  1965. show_banner() {
  1966. local os_name=$(grep -oP 'PRETTY_NAME="\K[^"]+' /etc/os-release || echo "Linux")
  1967. local up_time=$(uptime -p | sed 's/up //')
  1968. local ram_usage=$(free -m | awk '/^Mem:/{printf "%.2f", $3*100/$2}')
  1969. # Efficient CPU Load check (Load Average)
  1970. local cpu_load=$(cat /proc/loadavg | awk '{print $1}')
  1971. local online_users=0
  1972. # Optimize online user count: Get total active sshd procs roughly (may overcount if multiple procs per session but faster)
  1973. # Or just keep it if DB is small. Let's trust pgrep is okay for menu load.
  1974. if [[ -s "$DB_FILE" ]]; then
  1975. while IFS=: read -r user pass expiry limit; do
  1976. # Use pgrep -c for speed
  1977. local count=$(pgrep -c -u "$user" sshd)
  1978. online_users=$((online_users + count))
  1979. done < "$DB_FILE"
  1980. fi
  1981. local total_users=0
  1982. if [[ -s "$DB_FILE" ]]; then total_users=$(grep -c . "$DB_FILE"); fi
  1983. clear
  1984. echo
  1985. echo -e "${C_TITLE} FirewallFalcon Manager ${C_RESET}${C_DIM}| v3.5.0 Premium Edition${C_RESET}"
  1986. echo -e "${C_BLUE} ─────────────────────────────────────────────────────────${C_RESET}"
  1987. printf " ${C_GRAY}%-10s${C_RESET} %-20s ${C_GRAY}|${C_RESET} %s\n" "OS" "$os_name" "Uptime: $up_time"
  1988. printf " ${C_GRAY}%-10s${C_RESET} %-20s ${C_GRAY}|${C_RESET} %s\n" "Memory" "${ram_usage}% Used" "Online Sessions: ${C_WHITE}${online_users}${C_RESET}"
  1989. printf " ${C_GRAY}%-10s${C_RESET} %-20s ${C_GRAY}|${C_RESET} %s\n" "Users" "${total_users} Managed Accounts" "Sys Load (1m): ${C_GREEN}${cpu_load}${C_RESET}"
  1990. echo -e "${C_BLUE} ─────────────────────────────────────────────────────────${C_RESET}"
  1991. }
  1992. protocol_menu() {
  1993. while true; do
  1994. show_banner
  1995. local badvpn_status; if systemctl is-active --quiet badvpn; then badvpn_status="${C_STATUS_A}(Active)${C_RESET}"; else badvpn_status="${C_STATUS_I}(Inactive)${C_RESET}"; fi
  1996. local udp_custom_status; if systemctl is-active --quiet udp-custom; then udp_custom_status="${C_STATUS_A}(Active)${C_RESET}"; else udp_custom_status="${C_STATUS_I}(Inactive)${C_RESET}"; fi
  1997. local zivpn_status; if systemctl is-active --quiet zivpn.service; then zivpn_status="${C_STATUS_A}(Active)${C_RESET}"; else zivpn_status="${C_STATUS_I}(Inactive)${C_RESET}"; fi
  1998. local ssl_tunnel_text="SSL Tunnel (Port 444)"
  1999. local ssl_tunnel_status="${C_STATUS_I}(Inactive)${C_RESET}"
  2000. if systemctl is-active --quiet haproxy; then
  2001. local active_port
  2002. active_port=$(grep -oP 'bind \*:(\d+)' "$HAPROXY_CONFIG" 2>/dev/null | awk -F: '{print $2}')
  2003. if [[ -n "$active_port" ]]; then
  2004. ssl_tunnel_text="SSL Tunnel (Port $active_port)"
  2005. fi
  2006. ssl_tunnel_status="${C_STATUS_A}(Active)${C_RESET}"
  2007. fi
  2008. local dnstt_status; if systemctl is-active --quiet dnstt.service; then dnstt_status="${C_STATUS_A}(Active)${C_RESET}"; else dnstt_status="${C_STATUS_I}(Inactive)${C_RESET}"; fi
  2009. local falconproxy_status="${C_STATUS_I}(Inactive)${C_RESET}"
  2010. local falconproxy_ports=""
  2011. if systemctl is-active --quiet falconproxy; then
  2012. if [ -f "$FALCONPROXY_CONFIG_FILE" ]; then source "$FALCONPROXY_CONFIG_FILE"; fi
  2013. falconproxy_ports=" ($PORTS)"
  2014. falconproxy_status="${C_STATUS_A}(Active - ${INSTALLED_VERSION:-latest})${C_RESET}"
  2015. fi
  2016. local nginx_status; if systemctl is-active --quiet nginx; then nginx_status="${C_STATUS_A}(Active)${C_RESET}"; else nginx_status="${C_STATUS_I}(Inactive)${C_RESET}"; fi
  2017. local xui_status; if command -v x-ui &> /dev/null; then xui_status="${C_STATUS_A}(Installed)${C_RESET}"; else xui_status="${C_STATUS_I}(Not Installed)${C_RESET}"; fi
  2018. echo -e "\n ${C_TITLE}══════════════[ ${C_BOLD}🔌 PROTOCOL & PANEL MANAGEMENT ${C_RESET}${C_TITLE}]══════════════${C_RESET}"
  2019. echo -e " ${C_ACCENT}--- TUNNELLING PROTOCOLS---${C_RESET}"
  2020. printf " ${C_CHOICE}[ 1]${C_RESET} %-45s %s\n" "🚀 Install badvpn (UDP 7300)" "$badvpn_status"
  2021. printf " ${C_CHOICE}[ 2]${C_RESET} %-45s\n" "🗑️ Uninstall badvpn"
  2022. printf " ${C_CHOICE}[ 3]${C_RESET} %-45s %s\n" "🚀 Install udp-custom" "$udp_custom_status"
  2023. printf " ${C_CHOICE}[ 4]${C_RESET} %-45s\n" "🗑️ Uninstall udp-custom"
  2024. printf " ${C_CHOICE}[ 5]${C_RESET} %-45s %s\n" "🔒 Install ${ssl_tunnel_text}" "$ssl_tunnel_status"
  2025. printf " ${C_CHOICE}[ 6]${C_RESET} %-45s\n" "🗑️ Uninstall SSL Tunnel"
  2026. printf " ${C_CHOICE}[ 7]${C_RESET} %-45s %s\n" "📡 Install/View DNSTT (Port 53)" "$dnstt_status"
  2027. printf " ${C_CHOICE}[ 8]${C_RESET} %-45s\n" "🗑️ Uninstall DNSTT"
  2028. printf " ${C_CHOICE}[ 9]${C_RESET} %-45s %s\n" "🦅 Install Falcon Proxy (Select Version)" "$falconproxy_status"
  2029. printf " ${C_CHOICE}[10]${C_RESET} %-45s\n" "🗑️ Uninstall Falcon Proxy"
  2030. printf " ${C_CHOICE}[11]${C_RESET} %-45s %s\n" "🌐 Install/Manage Nginx Proxy (80/443)" "$nginx_status"
  2031. printf " ${C_CHOICE}[16]${C_RESET} %-45s %s\n" "🛡️ Install ZiVPN (UDP 5667)" "$zivpn_status"
  2032. printf " ${C_CHOICE}[17]${C_RESET} %-45s\n" "🗑️ Uninstall ZiVPN"
  2033. echo -e " ${C_ACCENT}--- 💻 MANAGEMENT PANELS ---${C_RESET}"
  2034. printf " ${C_CHOICE}[12]${C_RESET} %-45s %s\n" "💻 Install X-UI Panel" "$xui_status"
  2035. printf " ${C_CHOICE}[13]${C_RESET} %-45s\n" "🗑️ Uninstall X-UI Panel"
  2036. echo -e " ${C_DIM}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~${C_RESET}"
  2037. echo -e " ${C_WARN}[ 0]${C_RESET} ↩️ Return to Main Menu"
  2038. echo
  2039. read -p "$(echo -e ${C_PROMPT}"👉 Select an option: "${C_RESET})" choice
  2040. case $choice in
  2041. 1) install_badvpn; press_enter ;; 2) uninstall_badvpn; press_enter ;;
  2042. 3) install_udp_custom; press_enter ;; 4) uninstall_udp_custom; press_enter ;;
  2043. 5) install_ssl_tunnel; press_enter ;; 6) uninstall_ssl_tunnel; press_enter ;;
  2044. 7) install_dnstt; press_enter ;; 8) uninstall_dnstt; press_enter ;;
  2045. 9) install_falcon_proxy; press_enter ;; 10) uninstall_falcon_proxy; press_enter ;;
  2046. 11) nginx_proxy_menu ;;
  2047. 12) install_xui_panel; press_enter ;; 13) uninstall_xui_panel; press_enter ;;
  2048. 16) install_zivpn; press_enter ;; 17) uninstall_zivpn; press_enter ;;
  2049. 0) return ;;
  2050. *) invalid_option ;;
  2051. esac
  2052. done
  2053. }
  2054. install_dt_proxy_full() {
  2055. clear; show_banner
  2056. echo -e "${C_BOLD}${C_PURPLE}--- 🚀 Full DT Tunnel Installation ---${C_RESET}"
  2057. if [ -f "/usr/local/bin/main" ]; then
  2058. echo -e "\n${C_YELLOW}ℹ️ DT Proxy appears to be already installed.${C_RESET}"
  2059. echo -e "If you wish to reinstall, please uninstall it first."
  2060. return
  2061. fi
  2062. echo -e "\n${C_BLUE}--- Step 1 of 2: Installing DT Tunnel Mod ---${C_RESET}"
  2063. echo "This will download and run the prerequisite mod installer."
  2064. read -p "👉 Press [Enter] to continue or [Ctrl+C] to cancel."
  2065. if curl -sL https://raw.githubusercontent.com/firewallfalcons/ProxyMods/main/install.sh | bash; then
  2066. echo -e "\n${C_GREEN}✅ DT Tunnel Mod installed successfully.${C_RESET}"
  2067. else
  2068. echo -e "\n${C_RED}❌ ERROR: DT Tunnel Mod installation failed. Aborting.${C_RESET}"
  2069. return
  2070. fi
  2071. echo -e "\n${C_BLUE}--- Step 2 of 2: Installing DT Tunnel Proxy ---${C_RESET}"
  2072. echo "This will download and run the main DT Tunnel proxy installer."
  2073. read -p "👉 Press [Enter] to continue or [Ctrl+C] to cancel."
  2074. if bash <(curl -fsSL https://raw.githubusercontent.com/firewallfalcons/ProxyDT-Go-Releases/main/install.sh); then
  2075. echo -e "\n${C_GREEN}✅ DT Tunnel Proxy installed successfully.${C_RESET}"
  2076. echo -e "You can now manage it from the DT Proxy Management menu."
  2077. else
  2078. echo -e "\n${C_RED}❌ ERROR: DT Tunnel Proxy installation failed.${C_RESET}"
  2079. fi
  2080. }
  2081. launch_dt_proxy_menu() {
  2082. clear; show_banner
  2083. if [ -f "/usr/local/bin/main" ]; then
  2084. echo -e "\n${C_GREEN}✅ DT Proxy is installed. Launching its management panel...${C_RESET}"
  2085. sleep 2
  2086. /usr/local/bin/main
  2087. else
  2088. echo -e "\n${C_RED}❌ DT Proxy is not installed. Please use the install option first.${C_RESET}"
  2089. fi
  2090. }
  2091. uninstall_dt_proxy_full() {
  2092. clear; show_banner
  2093. echo -e "${C_BOLD}${C_PURPLE}--- 🗑️ Uninstall DT Proxy (Mod + Proxy) ---${C_RESET}"
  2094. if [ ! -f "/usr/local/bin/proxy" ] && [ ! -f "/usr/local/bin/main" ]; then
  2095. echo -e "\n${C_YELLOW}ℹ️ DT Proxy is not installed. Nothing to do.${C_RESET}"
  2096. return
  2097. fi
  2098. read -p "👉 Are you sure you want to PERMANENTLY delete DT Proxy and all its services? (y/n): " confirm
  2099. if [[ "$confirm" != "y" ]]; then
  2100. echo -e "\n${C_YELLOW}❌ Uninstallation cancelled.${C_RESET}"
  2101. return
  2102. fi
  2103. echo -e "\n${C_BLUE}🛑 Stopping and disabling all DT Proxy services...${C_RESET}"
  2104. systemctl list-units --type=service --state=running | grep 'proxy-' | awk '{print $1}' | xargs -r systemctl stop
  2105. systemctl list-unit-files --type=service | grep 'proxy-' | awk '{print $1}' | xargs -r systemctl disable
  2106. echo -e "\n${C_BLUE}🗑️ Removing files...${C_RESET}"
  2107. rm -f /etc/systemd/system/proxy-*.service
  2108. systemctl daemon-reload
  2109. rm -f /usr/local/bin/proxy
  2110. rm -f /usr/local/bin/main
  2111. rm -f "$HOME/.proxy_token"
  2112. rm -f /var/log/proxy-*.log
  2113. rm -f /usr/local/bin/install_mod
  2114. echo -e "\n${C_GREEN}✅ DT Proxy has been successfully uninstalled.${C_RESET}"
  2115. }
  2116. dt_proxy_menu() {
  2117. while true; do
  2118. show_banner
  2119. local dt_proxy_status
  2120. if [ -f "/usr/local/bin/main" ] && [ -f "/usr/local/bin/proxy" ]; then
  2121. dt_proxy_status="${C_STATUS_A}(Installed)${C_RESET}"
  2122. else
  2123. dt_proxy_status="${C_STATUS_I}(Not Installed)${C_RESET}"
  2124. fi
  2125. echo -e "\n ${C_TITLE}═════════════════[ ${C_BOLD}🚀 DT Proxy Management ${dt_proxy_status} ${C_RESET}${C_TITLE}]═════════════════${C_RESET}"
  2126. printf " ${C_CHOICE}[ 1]${C_RESET} %-45s\n" "🚀 Install DT Tunnel (Mod + Proxy)"
  2127. printf " ${C_CHOICE}[ 2]${C_RESET} %-45s\n" "▶️ Launch DT Tunnel Management Menu"
  2128. printf " ${C_DANGER}[ 3]${C_RESET} %-45s\n" "🗑️ Uninstall DT Tunnel (Mod + Proxy)"
  2129. echo -e " ${C_DIM}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~${C_RESET}"
  2130. echo -e " ${C_WARN}[ 0]${C_RESET} ↩️ Return to Main Menu"
  2131. echo
  2132. read -p "$(echo -e ${C_PROMPT}"👉 Select an option: "${C_RESET})" choice
  2133. case $choice in
  2134. 1) install_dt_proxy_full; press_enter ;;
  2135. 2) launch_dt_proxy_menu; press_enter ;;
  2136. 3) uninstall_dt_proxy_full; press_enter ;;
  2137. 0) return ;;
  2138. *) invalid_option ;;
  2139. esac
  2140. done
  2141. }
  2142. uninstall_script() {
  2143. clear; show_banner
  2144. echo -e "${C_RED}=====================================================${C_RESET}"
  2145. echo -e "${C_RED} 🔥 DANGER: UNINSTALL SCRIPT & ALL DATA 🔥 ${C_RESET}"
  2146. echo -e "${C_RED}=====================================================${C_RESET}"
  2147. echo -e "${C_YELLOW}This will PERMANENTLY remove this script and all its components, including:"
  2148. echo -e " - The main command ($(command -v menu))"
  2149. echo -e " - All configuration and user data ($DB_DIR)"
  2150. echo -e " - The active limiter service ($LIMITER_SERVICE)"
  2151. echo -e " - All installed services (badvpn, udp-custom, SSL Tunnel, Nginx, DNSTT, FalconProxy)"
  2152. echo -e "\n${C_RED}This action is irreversible.${C_RESET}"
  2153. echo ""
  2154. read -p "👉 Type 'yes' to confirm and proceed with uninstallation: " confirm
  2155. if [[ "$confirm" != "yes" ]]; then
  2156. echo -e "\n${C_GREEN}✅ Uninstallation cancelled.${C_RESET}"
  2157. return
  2158. fi
  2159. export UNINSTALL_MODE="silent"
  2160. echo -e "\n${C_BLUE}--- 💥 Starting Uninstallation 💥 ---${C_RESET}"
  2161. echo -e "\n${C_BLUE}🗑️ Removing active limiter service...${C_RESET}"
  2162. systemctl stop firewallfalcon-limiter &>/dev/null
  2163. systemctl disable firewallfalcon-limiter &>/dev/null
  2164. rm -f "$LIMITER_SERVICE"
  2165. rm -f "$LIMITER_SCRIPT"
  2166. chattr -i /etc/resolv.conf &>/dev/null
  2167. purge_nginx "silent"
  2168. uninstall_dnstt
  2169. uninstall_badvpn
  2170. uninstall_udp_custom
  2171. uninstall_ssl_tunnel
  2172. uninstall_falcon_proxy
  2173. uninstall_zivpn
  2174. delete_dns_record
  2175. echo -e "\n${C_BLUE}🔄 Reloading systemd daemon...${C_RESET}"
  2176. systemctl daemon-reload
  2177. echo -e "\n${C_BLUE}🗑️ Removing script and configuration files...${C_RESET}"
  2178. rm -rf "$BADVPN_BUILD_DIR"
  2179. rm -rf "$UDP_CUSTOM_DIR"
  2180. rm -rf "$DB_DIR"
  2181. rm -f "$(command -v menu)"
  2182. echo -e "\n${C_GREEN}=============================================${C_RESET}"
  2183. echo -e "${C_GREEN} Script has been successfully uninstalled. ${C_RESET}"
  2184. echo -e "${C_GREEN}=============================================${C_RESET}"
  2185. echo -e "\nAll associated files and services have been removed."
  2186. echo "The 'menu' command will no longer work."
  2187. exit 0
  2188. }
  2189. # --- NEW FEATURES ---
  2190. generate_client_config() {
  2191. local user=$1
  2192. local pass=$2
  2193. # Auto-detect Host
  2194. local host_ip=$(curl -s -4 icanhazip.com)
  2195. local host_domain="$host_ip"
  2196. if [ -f "$DNS_INFO_FILE" ]; then
  2197. local managed_domain=$(grep 'FULL_DOMAIN' "$DNS_INFO_FILE" | cut -d'"' -f2)
  2198. if [[ -n "$managed_domain" ]]; then host_domain="$managed_domain"; fi
  2199. fi
  2200. # Also check if Nginx Certbot is used
  2201. if [ -f "$NGINX_CONFIG_FILE" ]; then
  2202. local nginx_domain=$(grep -oP 'server_name \K[^\s;]+' "$NGINX_CONFIG_FILE" | head -n 1)
  2203. if [[ "$nginx_domain" != "_" && -n "$nginx_domain" ]]; then host_domain="$nginx_domain"; fi
  2204. fi
  2205. echo -e "\n${C_BOLD}${C_PURPLE}--- 📱 Client Connection Configuration ---${C_RESET}"
  2206. echo -e "${C_CYAN}Copy the details below to your clipboard:${C_RESET}\n"
  2207. echo -e "${C_YELLOW}========================================${C_RESET}"
  2208. echo -e "👤 ${C_BOLD}User Details${C_RESET}"
  2209. echo -e " • Username: ${C_WHITE}$user${C_RESET}"
  2210. echo -e " • Password: ${C_WHITE}$pass${C_RESET}"
  2211. echo -e " • Host/IP : ${C_WHITE}$host_domain${C_RESET}"
  2212. echo -e "${C_YELLOW}========================================${C_RESET}"
  2213. # 1. SSH Direct
  2214. echo -e "\n🔹 ${C_BOLD}SSH Direct${C_RESET}:"
  2215. echo -e " • Host: $host_domain"
  2216. echo -e " • Port: 22"
  2217. echo -e " • payload: (Standard SSH)"
  2218. # 2. SSL/TLS Tunnel (HAProxy or Nginx)
  2219. local ssl_port=""
  2220. local ssl_type=""
  2221. # Check HAProxy
  2222. if systemctl is-active --quiet haproxy; then
  2223. local haproxy_port=$(grep -oP 'bind \*:(\d+)' "$HAPROXY_CONFIG" 2>/dev/null | awk -F: '{print $2}')
  2224. if [[ -n "$haproxy_port" ]]; then ssl_port="$haproxy_port"; ssl_type="HAProxy"; fi
  2225. fi
  2226. # Check Nginx (Override if both exist, or show both)
  2227. if systemctl is-active --quiet nginx && [ -f "$NGINX_PORTS_FILE" ]; then
  2228. source "$NGINX_PORTS_FILE"
  2229. # Take the first TLS port
  2230. local nginx_ssl_port=$(echo "$TLS_PORTS" | awk '{print $1}')
  2231. if [[ -n "$nginx_ssl_port" ]]; then
  2232. if [[ -n "$ssl_port" ]]; then ssl_port="$ssl_port, $nginx_ssl_port"; else ssl_port="$nginx_ssl_port"; fi
  2233. ssl_type="Nginx/TLS"
  2234. fi
  2235. fi
  2236. if [[ -n "$ssl_port" ]]; then
  2237. echo -e "\n🔹 ${C_BOLD}SSL/TLS Tunnel ($ssl_type)${C_RESET}:"
  2238. echo -e " • Host: $host_domain"
  2239. echo -e " • Port(s): $ssl_port"
  2240. echo -e " • SNI (BugHost): $host_domain (or your preferred SNI)"
  2241. fi
  2242. # 3. UDP Custom
  2243. if systemctl is-active --quiet udp-custom; then
  2244. echo -e "\n🔹 ${C_BOLD}UDP Custom${C_RESET}:"
  2245. echo -e " • IP: $host_ip (Must use numeric IP)"
  2246. echo -e " • Port: 1-65535 (Exclude 53, 5300)"
  2247. echo -e " • Obfs: (None/Plain)"
  2248. fi
  2249. # 4. DNSTT
  2250. if systemctl is-active --quiet dnstt; then
  2251. if [ -f "$DNSTT_CONFIG_FILE" ]; then
  2252. source "$DNSTT_CONFIG_FILE"
  2253. echo -e "\n🔹 ${C_BOLD}DNSTT (SlowDNS)${C_RESET}:"
  2254. echo -e " • Nameserver: $TUNNEL_DOMAIN"
  2255. echo -e " • PubKey: $PUBLIC_KEY"
  2256. echo -e " • DNS IP: 1.1.1.1 / 8.8.8.8"
  2257. fi
  2258. fi
  2259. # 5. ZiVPN
  2260. if systemctl is-active --quiet zivpn; then
  2261. echo -e "\n🔹 ${C_BOLD}ZiVPN${C_RESET}:"
  2262. echo -e " • UDP Port: 5667"
  2263. echo -e " • Forwarded Ports: 6000-19999"
  2264. fi
  2265. echo -e "${C_YELLOW}========================================${C_RESET}"
  2266. press_enter
  2267. }
  2268. client_config_menu() {
  2269. _select_user_interface "--- 📱 Generate Client Config ---"
  2270. local u=$SELECTED_USER
  2271. if [[ "$u" == "NO_USERS" || -z "$u" ]]; then return; fi
  2272. # We need to find the password. It's in the DB.
  2273. local pass=$(grep "^$u:" "$DB_FILE" | cut -d: -f2)
  2274. generate_client_config "$u" "$pass"
  2275. }
  2276. # Lightweight Bash Monitor (No vnStat required)
  2277. simple_live_monitor() {
  2278. local iface=$1
  2279. echo -e "\n${C_BLUE}⚡ Starting Lightweight Traffic Monitor for $iface...${C_RESET}"
  2280. echo -e "${C_DIM}Press [Ctrl+C] to stop.${C_RESET}\n"
  2281. # Get initial values
  2282. local rx1=$(cat /sys/class/net/$iface/statistics/rx_bytes)
  2283. local tx1=$(cat /sys/class/net/$iface/statistics/tx_bytes)
  2284. printf "%-15s | %-15s\n" "⬇️ Download" "⬆️ Upload"
  2285. echo "-----------------------------------"
  2286. while true; do
  2287. sleep 1
  2288. local rx2=$(cat /sys/class/net/$iface/statistics/rx_bytes)
  2289. local tx2=$(cat /sys/class/net/$iface/statistics/tx_bytes)
  2290. # Calculate diffs
  2291. local rx_diff=$((rx2 - rx1))
  2292. local tx_diff=$((tx2 - tx1))
  2293. # Convert to KB/s
  2294. local rx_kbs=$((rx_diff / 1024))
  2295. local tx_kbs=$((tx_diff / 1024))
  2296. # Formatting for MB/s if > 1024 KB
  2297. if [ $rx_kbs -gt 1024 ]; then rx_fmt=$(awk "BEGIN {printf \"%.2f MB/s\", $rx_kbs/1024}"); else rx_fmt="${rx_kbs} KB/s"; fi
  2298. if [ $tx_kbs -gt 1024 ]; then tx_fmt=$(awk "BEGIN {printf \"%.2f MB/s\", $tx_kbs/1024}"); else tx_fmt="${tx_kbs} KB/s"; fi
  2299. printf "\r%-15s | %-15s" "$rx_fmt" "$tx_fmt"
  2300. # Reset for next loop
  2301. rx1=$rx2
  2302. tx1=$tx2
  2303. done
  2304. }
  2305. traffic_monitor_menu() {
  2306. clear; show_banner
  2307. echo -e "${C_BOLD}${C_PURPLE}--- 📈 Network Traffic Monitor ---${C_RESET}"
  2308. # Find active interface
  2309. local iface=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)
  2310. echo -e "\nInterface: ${C_CYAN}${iface}${C_RESET}"
  2311. echo -e "\n${C_BOLD}Select a monitoring option:${C_RESET}\n"
  2312. printf " ${C_CHOICE}[ 1]${C_RESET} %-40s\n" "⚡ Live Monitor ${C_DIM}(Lightweight, No Install)${C_RESET}"
  2313. printf " ${C_CHOICE}[ 2]${C_RESET} %-40s\n" "📊 View Total Traffic Since Boot"
  2314. printf " ${C_CHOICE}[ 3]${C_RESET} %-40s\n" "📅 Daily/Monthly Logs ${C_DIM}(Requires vnStat)${C_RESET}"
  2315. echo -e "\n ${C_WARN}[ 0]${C_RESET} ↩️ Return"
  2316. echo
  2317. read -p "👉 Enter choice: " t_choice
  2318. case $t_choice in
  2319. 1)
  2320. simple_live_monitor "$iface"
  2321. ;;
  2322. 2)
  2323. local rx_total=$(cat /sys/class/net/$iface/statistics/rx_bytes)
  2324. local tx_total=$(cat /sys/class/net/$iface/statistics/tx_bytes)
  2325. local rx_mb=$((rx_total / 1024 / 1024))
  2326. local tx_mb=$((tx_total / 1024 / 1024))
  2327. echo -e "\n${C_BLUE}📊 Total Traffic (Since Boot):${C_RESET}"
  2328. echo -e " ⬇️ Download: ${C_WHITE}${rx_mb} MB${C_RESET}"
  2329. echo -e " ⬆️ Upload: ${C_WHITE}${tx_mb} MB${C_RESET}"
  2330. press_enter
  2331. ;;
  2332. 3)
  2333. # vnStat Logic
  2334. if ! command -v vnstat &> /dev/null; then
  2335. echo -e "\n${C_YELLOW}⚠️ vnStat is not installed.${C_RESET}"
  2336. echo -e " This tool provides persistent history (Daily/Monthly reports)."
  2337. echo -e " It is lightweight but requires installation."
  2338. read -p "👉 Install vnStat now? (y/n): " confirm
  2339. if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
  2340. echo -e "\n${C_BLUE}📦 Installing vnStat...${C_RESET}"
  2341. apt-get update >/dev/null 2>&1
  2342. apt-get install -y vnstat >/dev/null 2>&1
  2343. systemctl enable vnstat >/dev/null 2>&1
  2344. systemctl restart vnstat >/dev/null 2>&1
  2345. local default_iface=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)
  2346. vnstat --add -i "$default_iface" >/dev/null 2>&1
  2347. echo -e "${C_GREEN}✅ Installed.${C_RESET}"
  2348. sleep 1
  2349. else
  2350. return
  2351. fi
  2352. fi
  2353. echo
  2354. vnstat -i "$iface"
  2355. echo -e "\n${C_DIM}Run 'vnstat -d' or 'vnstat -m' manually for specific views.${C_RESET}"
  2356. press_enter
  2357. ;;
  2358. *) return ;;
  2359. esac
  2360. }
  2361. torrent_block_menu() {
  2362. clear; show_banner
  2363. echo -e "${C_BOLD}${C_PURPLE}--- 🚫 Torrent Blocking (Anti-Torrent) ---${C_RESET}"
  2364. # Check status
  2365. local torrent_status="${C_STATUS_I}Disabled${C_RESET}"
  2366. if iptables -L FORWARD | grep -q "ipp2p"; then
  2367. torrent_status="${C_STATUS_A}Enabled${C_RESET}"
  2368. elif iptables -L OUTPUT | grep -q "BitTorrent"; then
  2369. # Fallback check for string matching
  2370. torrent_status="${C_STATUS_A}Enabled${C_RESET}"
  2371. fi
  2372. echo -e "\n${C_WHITE}Current Status: ${torrent_status}${C_RESET}"
  2373. echo -e "${C_DIM}This feature uses iptables string matching to block common torrent keywords.${C_RESET}"
  2374. echo -e "\n${C_BOLD}Select an action:${C_RESET}\n"
  2375. printf " ${C_CHOICE}[ 1]${C_RESET} %-40s\n" "🔒 Enable Torrent Blocking"
  2376. printf " ${C_CHOICE}[ 2]${C_RESET} %-40s\n" "🔓 Disable Torrent Blocking"
  2377. echo -e "\n ${C_WARN}[ 0]${C_RESET} ↩️ Return"
  2378. echo
  2379. read -p "👉 Enter choice: " b_choice
  2380. case $b_choice in
  2381. 1)
  2382. echo -e "\n${C_BLUE}🛡️ Applying Anti-Torrent rules...${C_RESET}"
  2383. # Clean old rules first to avoid duplicates
  2384. _flush_torrent_rules
  2385. # Block Common Torrent Ports/Keywords
  2386. # String matching using iptables extension
  2387. iptables -A FORWARD -m string --string "BitTorrent" --algo bm -j DROP
  2388. iptables -A FORWARD -m string --string "BitTorrent protocol" --algo bm -j DROP
  2389. iptables -A FORWARD -m string --string "peer_id=" --algo bm -j DROP
  2390. iptables -A FORWARD -m string --string ".torrent" --algo bm -j DROP
  2391. iptables -A FORWARD -m string --string "announce.php?passkey=" --algo bm -j DROP
  2392. iptables -A FORWARD -m string --string "torrent" --algo bm -j DROP
  2393. iptables -A FORWARD -m string --string "info_hash" --algo bm -j DROP
  2394. iptables -A FORWARD -m string --string "get_peers" --algo bm -j DROP
  2395. iptables -A FORWARD -m string --string "find_node" --algo bm -j DROP
  2396. # Same for OUTPUT to be safe
  2397. iptables -A OUTPUT -m string --string "BitTorrent" --algo bm -j DROP
  2398. iptables -A OUTPUT -m string --string "BitTorrent protocol" --algo bm -j DROP
  2399. iptables -A OUTPUT -m string --string "peer_id=" --algo bm -j DROP
  2400. iptables -A OUTPUT -m string --string ".torrent" --algo bm -j DROP
  2401. iptables -A OUTPUT -m string --string "announce.php?passkey=" --algo bm -j DROP
  2402. iptables -A OUTPUT -m string --string "torrent" --algo bm -j DROP
  2403. iptables -A OUTPUT -m string --string "info_hash" --algo bm -j DROP
  2404. iptables -A OUTPUT -m string --string "get_peers" --algo bm -j DROP
  2405. iptables -A OUTPUT -m string --string "find_node" --algo bm -j DROP
  2406. # Attempt to save if iptables-persistent exists
  2407. if dpkg -s iptables-persistent &>/dev/null; then
  2408. netfilter-persistent save &>/dev/null
  2409. fi
  2410. echo -e "${C_GREEN}✅ Torrent Blocking Enabled.${C_RESET}"
  2411. press_enter
  2412. ;;
  2413. 2)
  2414. echo -e "\n${C_BLUE}🔓 Removing Anti-Torrent rules...${C_RESET}"
  2415. _flush_torrent_rules
  2416. if dpkg -s iptables-persistent &>/dev/null; then
  2417. netfilter-persistent save &>/dev/null
  2418. fi
  2419. echo -e "${C_GREEN}✅ Torrent Blocking Disabled.${C_RESET}"
  2420. press_enter
  2421. ;;
  2422. *) return ;;
  2423. esac
  2424. }
  2425. _flush_torrent_rules() {
  2426. # Helper to remove rules containing specific strings
  2427. # This is a bit brute-force but effective for this script's scope
  2428. iptables -D FORWARD -m string --string "BitTorrent" --algo bm -j DROP 2>/dev/null
  2429. iptables -D FORWARD -m string --string "BitTorrent protocol" --algo bm -j DROP 2>/dev/null
  2430. iptables -D FORWARD -m string --string "peer_id=" --algo bm -j DROP 2>/dev/null
  2431. iptables -D FORWARD -m string --string ".torrent" --algo bm -j DROP 2>/dev/null
  2432. iptables -D FORWARD -m string --string "announce.php?passkey=" --algo bm -j DROP 2>/dev/null
  2433. iptables -D FORWARD -m string --string "torrent" --algo bm -j DROP 2>/dev/null
  2434. iptables -D FORWARD -m string --string "info_hash" --algo bm -j DROP 2>/dev/null
  2435. iptables -D FORWARD -m string --string "get_peers" --algo bm -j DROP 2>/dev/null
  2436. iptables -D FORWARD -m string --string "find_node" --algo bm -j DROP 2>/dev/null
  2437. iptables -D OUTPUT -m string --string "BitTorrent" --algo bm -j DROP 2>/dev/null
  2438. iptables -D OUTPUT -m string --string "BitTorrent protocol" --algo bm -j DROP 2>/dev/null
  2439. iptables -D OUTPUT -m string --string "peer_id=" --algo bm -j DROP 2>/dev/null
  2440. iptables -D OUTPUT -m string --string ".torrent" --algo bm -j DROP 2>/dev/null
  2441. iptables -D OUTPUT -m string --string "announce.php?passkey=" --algo bm -j DROP 2>/dev/null
  2442. iptables -D OUTPUT -m string --string "torrent" --algo bm -j DROP 2>/dev/null
  2443. iptables -D OUTPUT -m string --string "info_hash" --algo bm -j DROP 2>/dev/null
  2444. iptables -D OUTPUT -m string --string "get_peers" --algo bm -j DROP 2>/dev/null
  2445. iptables -D OUTPUT -m string --string "find_node" --algo bm -j DROP 2>/dev/null
  2446. }
  2447. auto_reboot_menu() {
  2448. clear; show_banner
  2449. echo -e "${C_BOLD}${C_PURPLE}--- 🔄 Auto-Reboot Management ---${C_RESET}"
  2450. # Check status
  2451. local cron_check=$(crontab -l 2>/dev/null | grep "systemctl reboot")
  2452. local status="${C_STATUS_I}Disabled${C_RESET}"
  2453. if [[ -n "$cron_check" ]]; then
  2454. status="${C_STATUS_A}Active (Midnight)${C_RESET}"
  2455. fi
  2456. echo -e "\n${C_WHITE}Current Status: ${status}${C_RESET}"
  2457. echo -e "\n${C_BOLD}Select an action:${C_RESET}\n"
  2458. printf " ${C_CHOICE}[ 1]${C_RESET} %-40s\n" "🕐 Enable Daily Reboot (00:00 midnight)"
  2459. printf " ${C_CHOICE}[ 2]${C_RESET} %-40s\n" "❌ Disable Auto-Reboot"
  2460. echo -e "\n ${C_WARN}[ 0]${C_RESET} ↩️ Return"
  2461. echo
  2462. read -p "👉 Enter choice: " r_choice
  2463. case $r_choice in
  2464. 1)
  2465. # Remove existing to prevent duplicates
  2466. (crontab -l 2>/dev/null | grep -v "systemctl reboot") | crontab -
  2467. # Add new job
  2468. (crontab -l 2>/dev/null; echo "0 0 * * * systemctl reboot") | crontab -
  2469. echo -e "\n${C_GREEN}✅ Auto-reboot scheduled for every day at 00:00.${C_RESET}"
  2470. press_enter
  2471. ;;
  2472. 2)
  2473. (crontab -l 2>/dev/null | grep -v "systemctl reboot") | crontab -
  2474. echo -e "\n${C_GREEN}✅ Auto-reboot disabled.${C_RESET}"
  2475. press_enter
  2476. ;;
  2477. *) return ;;
  2478. esac
  2479. }
  2480. press_enter() {
  2481. echo -e "\nPress ${C_YELLOW}[Enter]${C_RESET} to return to the menu..." && read -r
  2482. }
  2483. invalid_option() {
  2484. echo -e "\n${C_RED}❌ Invalid option.${C_RESET}" && sleep 1
  2485. }
  2486. main_menu() {
  2487. while true; do
  2488. export UNINSTALL_MODE="interactive"
  2489. show_banner
  2490. echo
  2491. echo -e " ${C_TITLE}═══════════════[ ${C_BOLD}👤 USER MANAGEMENT ${C_RESET}${C_TITLE}]═══════════════${C_RESET}"
  2492. printf " ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "1" "Create New User" "5" "Unlock User Account"
  2493. printf " ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "2" "Delete User" "6" "Edit User Details"
  2494. printf " ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "3" "Renew User Account" "7" "List Managed Users"
  2495. printf " ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "4" "Lock User Account" "8" "Generate Client Config"
  2496. echo
  2497. echo -e " ${C_TITLE}════════════[ ${C_BOLD}🌐 VPN & PROTOCOLS ${C_RESET}${C_TITLE}]═════════════${C_RESET}"
  2498. printf " ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "9" "Protocol Manager" "11" "Traffic Monitor (Lite)"
  2499. printf " ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "10" "DT Proxy Manager" "12" "Block Torrent (Anti-P2P)"
  2500. echo
  2501. echo -e " ${C_TITLE}════════════[ ${C_BOLD}⚙️ SYSTEM SETTINGS ${C_RESET}${C_TITLE}]═════════════${C_RESET}"
  2502. printf " ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "13" "CloudFlare Free Domain" "16" "Backup User Data"
  2503. printf " ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "14" "SSH Banner Config" "17" "Restore User Data"
  2504. printf " ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "15" "Auto-Reboot Task" "18" "Cleanup Expired Users"
  2505. echo
  2506. echo -e " ${C_DANGER}═══════════════════[ ${C_BOLD}🔥 DANGER ZONE ${C_RESET}${C_DANGER}]═══════════════════${C_RESET}"
  2507. echo -e " ${C_DANGER}[99]${C_RESET} Uninstall Script ${C_WARN}[ 0]${C_RESET} Exit"
  2508. echo
  2509. read -p "$(echo -e ${C_PROMPT}"👉 Select an option: "${C_RESET})" choice
  2510. case $choice in
  2511. 1) create_user; press_enter ;;
  2512. 2) delete_user; press_enter ;;
  2513. 3) renew_user; press_enter ;;
  2514. 4) lock_user; press_enter ;;
  2515. 5) unlock_user; press_enter ;;
  2516. 6) edit_user; press_enter ;;
  2517. 7) list_users; press_enter ;;
  2518. 8) client_config_menu; press_enter ;;
  2519. 9) protocol_menu ;;
  2520. 10) dt_proxy_menu ;;
  2521. 11) traffic_monitor_menu ;;
  2522. 12) torrent_block_menu ;;
  2523. 13) dns_menu; press_enter ;;
  2524. 14) ssh_banner_menu ;;
  2525. 15) auto_reboot_menu ;;
  2526. 16) backup_user_data; press_enter ;;
  2527. 17) restore_user_data; press_enter ;;
  2528. 18) cleanup_expired; press_enter ;;
  2529. 99) uninstall_script ;;
  2530. 0) exit 0 ;;
  2531. *) invalid_option ;;
  2532. esac
  2533. done
  2534. }
  2535. if [[ "$1" == "--install-setup" ]]; then
  2536. initial_setup
  2537. exit 0
  2538. fi
  2539. main_menu