@@ -584,6 +584,124 @@ detect_socks_auth() {
584584 return 1
585585}
586586
587+ # ─── Configure SOCKS Auth (manage menu) ──────────────────────────────────────
588+
589+ do_configure_socks_auth () {
590+ banner
591+ print_header " Configure SOCKS5 Authentication"
592+
593+ if [[ $EUID -ne 0 ]]; then
594+ print_fail " Not running as root."
595+ exit 1
596+ fi
597+
598+ if ! command -v dnstm & > /dev/null; then
599+ print_fail " dnstm is not installed."
600+ exit 1
601+ fi
602+
603+ # Show current state
604+ echo " "
605+ detect_socks_auth || true
606+ if [[ " $SOCKS_AUTH " == true ]]; then
607+ echo -e " ${BOLD} Current status:${NC} ${GREEN} Enabled${NC} "
608+ echo -e " ${DIM} Username: ${SOCKS_USER}${NC} "
609+ echo " "
610+ echo -e " ${BOLD} 1)${NC} Change credentials"
611+ echo -e " ${BOLD} 2)${NC} Disable authentication"
612+ echo -e " ${BOLD} 0)${NC} Cancel"
613+ echo " "
614+ local choice=" "
615+ read -rp " Select [0-2]: " choice || exit 0
616+ case " $choice " in
617+ 1)
618+ echo " "
619+ ;;
620+ 2)
621+ echo " "
622+ print_info " Disabling SOCKS5 authentication..."
623+ if dnstm backend auth -t socks --disable; then
624+ print_ok " SOCKS5 authentication disabled"
625+ sleep 2
626+ if pgrep -x microsocks & > /dev/null || systemctl is-active --quiet microsocks 2> /dev/null; then
627+ print_ok " microsocks restarted without authentication"
628+ else
629+ print_warn " microsocks may not have restarted — check: systemctl status microsocks"
630+ fi
631+ else
632+ print_fail " Failed to disable authentication"
633+ fi
634+ exit 0
635+ ;;
636+ * )
637+ exit 0
638+ ;;
639+ esac
640+ else
641+ echo -e " ${BOLD} Current status:${NC} ${RED} Disabled (open proxy)${NC} "
642+ echo " "
643+ if ! prompt_yn " Enable SOCKS5 authentication?" " y" ; then
644+ print_info " Cancelled."
645+ exit 0
646+ fi
647+ echo " "
648+ fi
649+
650+ # Collect credentials
651+ local new_user new_pass
652+ new_user=$( prompt_input " Enter SOCKS proxy username" " proxy" )
653+ new_user=$( echo " $new_user " | sed ' s/^[[:space:]]*//;s/[[:space:]]*$//' )
654+ if [[ -z " $new_user " ]]; then
655+ print_fail " Username cannot be empty"
656+ exit 1
657+ fi
658+ if [[ " $new_user " == * " |" * || " $new_user " == * " :" * ]]; then
659+ print_fail " Username cannot contain | or : characters"
660+ exit 1
661+ fi
662+
663+ new_pass=$( prompt_input " Enter SOCKS proxy password" )
664+ new_pass=$( echo " $new_pass " | sed ' s/^[[:space:]]*//;s/[[:space:]]*$//' )
665+ if [[ -z " $new_pass " ]]; then
666+ print_fail " Password cannot be empty"
667+ exit 1
668+ fi
669+ if [[ " $new_pass " == * " |" * ]]; then
670+ print_fail " Password cannot contain the | character"
671+ exit 1
672+ fi
673+
674+ echo " "
675+ print_info " Applying SOCKS5 authentication..."
676+ if dnstm backend auth -t socks -u " $new_user " -p " $new_pass " ; then
677+ print_ok " SOCKS5 authentication enabled (user: ${new_user} )"
678+ sleep 2
679+ if pgrep -x microsocks & > /dev/null || systemctl is-active --quiet microsocks 2> /dev/null; then
680+ print_ok " microsocks restarted with authentication"
681+ else
682+ print_warn " microsocks may not have restarted — check: systemctl status microsocks"
683+ fi
684+
685+ # Verify auth enforcement
686+ local socks_port=" "
687+ socks_port=$( ss -tlnp 2> /dev/null | grep microsocks | awk ' {for(i=1;i<=NF;i++) if($i ~ /:[0-9]+$/) {split($i,a,":"); print a[length(a)]; exit}}' || true)
688+ if [[ -z " $socks_port " ]]; then
689+ socks_port=" 19801"
690+ fi
691+ local noauth_test
692+ noauth_test=$( curl -s --max-time 5 --socks5 " 127.0.0.1:${socks_port} " https://api.ipify.org 2> /dev/null || true)
693+ if [[ -z " $noauth_test " ]]; then
694+ print_ok " Auth enforced: unauthenticated connections are rejected"
695+ else
696+ print_warn " Auth NOT enforced: proxy still works without credentials!"
697+ print_info " Try restarting: systemctl restart microsocks"
698+ fi
699+ else
700+ print_fail " Failed to configure SOCKS5 authentication"
701+ print_info " Try manually: dnstm backend auth -t socks -u ${new_user} -p <password>"
702+ fi
703+ }
704+
587705# ─── --status ───────────────────────────────────────────────────────────────────
588706
589707do_status () {
@@ -1709,16 +1827,17 @@ do_manage() {
17091827 echo -e " ${BOLD} 3)${NC} Remove tunnel ${DIM} (pick one to remove)${NC} "
17101828 echo -e " ${BOLD} 4)${NC} Add backup domain ${DIM} (new domain → 4 more tunnels)${NC} "
17111829 echo -e " ${BOLD} 5)${NC} Manage SSH users ${DIM} (add, list, update, delete)${NC} "
1712- echo -e " ${BOLD} 6)${NC} Apply hardening ${DIM} (systemd security for all services)${NC} "
1830+ echo -e " ${BOLD} 6)${NC} Configure SOCKS auth ${DIM} (enable, disable, or change credentials)${NC} "
1831+ echo -e " ${BOLD} 7)${NC} Apply hardening ${DIM} (systemd security for all services)${NC} "
17131832 echo " "
17141833 echo -e " ${DIM} ──────────────────────────────────────────────${NC} "
1715- echo -e " ${BOLD}${RED} 7 )${NC} ${RED} Uninstall everything${NC} "
1834+ echo -e " ${BOLD}${RED} 8 )${NC} ${RED} Uninstall everything${NC} "
17161835 echo " "
17171836 echo -e " ${BOLD} 0)${NC} Exit"
17181837 echo " "
17191838
17201839 local choice=" "
1721- read -rp " Select [0-7 ]: " choice || break
1840+ read -rp " Select [0-8 ]: " choice || break
17221841
17231842 case " $choice " in
17241843 1)
@@ -1737,9 +1856,12 @@ do_manage() {
17371856 ( trap - INT; do_manage_users ) || true
17381857 ;;
17391858 6)
1740- ( trap - INT; do_harden ) || true
1859+ ( trap - INT; do_configure_socks_auth ) || true
17411860 ;;
17421861 7)
1862+ ( trap - INT; do_harden ) || true
1863+ ;;
1864+ 8)
17431865 ( trap - INT; do_uninstall ) || true
17441866 # If uninstall succeeded, dnstm is gone — exit menu
17451867 hash -d dnstm 2> /dev/null || true
@@ -1758,7 +1880,7 @@ do_manage() {
17581880 continue
17591881 ;;
17601882 * )
1761- print_warn " Invalid choice. Enter 0-7 ."
1883+ print_warn " Invalid choice. Enter 0-8 ."
17621884 sleep 1
17631885 continue
17641886 ;;
@@ -2503,8 +2625,16 @@ step_verify_microsocks() {
25032625 # Apply SOCKS authentication via dnstm (v0.6.8+) — only if microsocks is running
25042626 if [[ " $microsocks_running " == true && " $SOCKS_AUTH " == true && -n " $SOCKS_USER " && -n " $SOCKS_PASS " ]]; then
25052627 print_info " Configuring SOCKS5 authentication via dnstm..."
2506- if dnstm backend auth -t socks -u " $SOCKS_USER " -p " $SOCKS_PASS " 2> /dev/null ; then
2628+ if dnstm backend auth -t socks -u " $SOCKS_USER " -p " $SOCKS_PASS " ; then
25072629 print_ok " SOCKS5 authentication enabled (user: ${SOCKS_USER} )"
2630+ # dnstm backend auth rewrites ExecStart and restarts microsocks;
2631+ # give it a moment to come back up
2632+ sleep 2
2633+ if pgrep -x microsocks & > /dev/null || systemctl is-active --quiet microsocks 2> /dev/null; then
2634+ print_ok " microsocks restarted with authentication"
2635+ else
2636+ print_warn " microsocks may not have restarted — check: systemctl status microsocks"
2637+ fi
25082638 else
25092639 print_warn " Failed to configure SOCKS5 authentication via dnstm"
25102640 print_info " Try manually: dnstm backend auth -t socks -u ${SOCKS_USER} -p <password>"
@@ -2546,6 +2676,18 @@ step_verify_microsocks() {
25462676 print_warn " SOCKS proxy test failed (this may be OK if internet is restricted)"
25472677 print_info " The proxy may still work for DNS tunnel clients"
25482678 fi
2679+
2680+ # Negative test: verify unauthenticated access is rejected when auth is enabled
2681+ if [[ " $SOCKS_AUTH " == true && -n " $test_ip " ]]; then
2682+ local noauth_ip
2683+ noauth_ip=$( curl -s --max-time 5 --socks5 " 127.0.0.1:${socks_port} " https://api.ipify.org 2> /dev/null || true)
2684+ if [[ -z " $noauth_ip " ]]; then
2685+ print_ok " Auth enforced: unauthenticated connections are rejected"
2686+ else
2687+ print_warn " Auth NOT enforced: proxy works without credentials!"
2688+ print_info " Try: dnstm backend auth -t socks -u ${SOCKS_USER} -p <password>"
2689+ fi
2690+ fi
25492691}
25502692
25512693# ─── STEP 10: SSH User (Optional) ──────────────────────────────────────────────
@@ -2662,6 +2804,18 @@ step_tests() {
26622804 if [[ -n " $socks_result " ]]; then
26632805 print_ok " SOCKS proxy: PASS (IP: ${socks_result} ) on port ${socks_port} "
26642806 pass=$(( pass + 1 ))
2807+ # Verify auth enforcement
2808+ if [[ " $SOCKS_AUTH " == true ]]; then
2809+ local noauth_result
2810+ noauth_result=$( curl -s --max-time 5 --socks5 " 127.0.0.1:${socks_port} " https://api.ipify.org 2> /dev/null || true)
2811+ if [[ -z " $noauth_result " ]]; then
2812+ print_ok " SOCKS auth enforcement: PASS (unauthenticated rejected)"
2813+ pass=$(( pass + 1 ))
2814+ else
2815+ print_fail " SOCKS auth enforcement: FAIL (works without credentials!)"
2816+ fail=$(( fail + 1 ))
2817+ fi
2818+ fi
26652819 elif ss -tlnp 2> /dev/null | grep -q " microsocks" ; then
26662820 print_warn " SOCKS proxy: LISTENING on port ${socks_port} but connectivity test failed"
26672821 print_info " microsocks is running but outbound may be blocked or tunnels not ready"
0 commit comments