Created
February 6, 2026 06:29
-
-
Save ankushKun/e0234e9f948296e9a8f11b5b0df396b6 to your computer and use it in GitHub Desktop.
Auto Fortinet Firewall Login for College WiFi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # ============================================ | |
| # Firewall Auto-Login Script | |
| # ============================================ | |
| # Automatically logs into the campus firewall | |
| # when internet connectivity is lost. | |
| # | |
| # Usage: | |
| # 1. Fill in your credentials below | |
| # 2. chmod +x firewall-login.sh | |
| # 3. ./firewall-login.sh | |
| # ============================================ | |
| # --- Configuration --- | |
| USERNAME="YOUR_STUDENT_ID" | |
| PASSWORD="YOUR_PASWORD" | |
| FIREWALL_URL="http://172.16.2.1:1000" | |
| CHECK_URL="http://detectportal.firefox.com/canonical.html" | |
| CHECK_INTERVAL=30 # seconds between connectivity checks | |
| KEEPALIVE_INTERVAL=300 # seconds between keepalive pings (5 min) | |
| LAST_KEEPALIVE=0 | |
| KEEPALIVE_URL="" | |
| # --- Colors --- | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| NC='\033[0m' # No Color | |
| log() { | |
| echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | |
| } | |
| check_internet() { | |
| # The firewall allows ping/DNS through but blocks HTTP until authenticated. | |
| # So we must check actual HTTP access. We fetch a known URL and check if | |
| # the response contains the firewall login page (fgtauth) or not. | |
| RESPONSE_BODY=$(curl -s --max-time 5 "http://www.gstatic.com/generate_204" -w "%{http_code}" -o /tmp/fw_check.txt 2>/dev/null) | |
| HTTP_CODE="$RESPONSE_BODY" | |
| BODY=$(cat /tmp/fw_check.txt 2>/dev/null) | |
| # generate_204 returns HTTP 204 with empty body when internet works. | |
| # If firewall intercepts, it returns 200/302 with the login page HTML. | |
| if [ "$HTTP_CODE" = "204" ]; then | |
| return 0 # internet is working | |
| fi | |
| # Also check: if body contains firewall/fgtauth, definitely not logged in | |
| if echo "$BODY" | grep -q "fgtauth\|Firewall Authentication\|magic"; then | |
| return 1 # firewall login page intercepted | |
| fi | |
| # If we got 200 with empty or non-firewall body, could be working | |
| if [ "$HTTP_CODE" = "200" ] && [ -z "$BODY" ]; then | |
| return 0 | |
| fi | |
| return 1 | |
| } | |
| do_login() { | |
| log "${YELLOW}Internet not available. Attempting firewall login...${NC}" | |
| # Step 1: Fetch the login page to get the current 'magic' token. | |
| # The firewall redirects HTTP requests to http://172.16.2.1:1000/fgtauth?<id> | |
| # We need to follow that redirect to get the actual login page with the magic token. | |
| # First, try hitting CHECK_URL and follow redirects to land on the firewall page | |
| LOGIN_PAGE=$(curl -s -L --max-time 10 "$CHECK_URL" 2>/dev/null) | |
| EFFECTIVE_URL=$(curl -s -o /dev/null -w "%{url_effective}" -L --max-time 10 "$CHECK_URL" 2>/dev/null) | |
| log "Redirected to: ${EFFECTIVE_URL}" | |
| # If that didn't return a page with a magic token, the firewall might use | |
| # a non-HTTP redirect (like HTML meta refresh or JS). Try to extract the | |
| # redirect URL from the response body instead. | |
| if ! echo "$LOGIN_PAGE" | grep -q 'name="magic"'; then | |
| # Check if the response contains a redirect URL to the firewall | |
| REDIRECT_URL=$(echo "$LOGIN_PAGE" | grep -o 'http://172\.16\.[0-9.]*:1000/fgtauth?[^"'"'"' <]*' | head -1) | |
| if [ -n "$REDIRECT_URL" ]; then | |
| log "Found firewall redirect URL: ${REDIRECT_URL}" | |
| LOGIN_PAGE=$(curl -s --max-time 10 "$REDIRECT_URL" 2>/dev/null) | |
| EFFECTIVE_URL="$REDIRECT_URL" | |
| else | |
| # Last resort: try any HTTP URL on the firewall host | |
| LOGIN_PAGE=$(curl -s -L --max-time 10 "http://172.16.2.1:1000/" 2>/dev/null) | |
| EFFECTIVE_URL="http://172.16.2.1:1000/" | |
| fi | |
| fi | |
| if [ -z "$LOGIN_PAGE" ]; then | |
| log "${RED}Could not reach the firewall login page.${NC}" | |
| return 1 | |
| fi | |
| # If the page doesn't contain a magic token at this point, | |
| # we might already be logged in or got an unexpected page | |
| if ! echo "$LOGIN_PAGE" | grep -q 'name="magic"'; then | |
| log "${YELLOW}No login form found. Might already be authenticated. Waiting for next cycle.${NC}" | |
| return 1 | |
| fi | |
| # Step 2: Extract the magic token and redirect URL | |
| MAGIC=$(echo "$LOGIN_PAGE" | grep -o 'name="magic" value="[^"]*"' | grep -o 'value="[^"]*"' | cut -d'"' -f2) | |
| REDIR=$(echo "$LOGIN_PAGE" | grep -o 'name="4Tredir" value="[^"]*"' | grep -o 'value="[^"]*"' | cut -d'"' -f2) | |
| if [ -z "$MAGIC" ]; then | |
| log "${RED}Could not extract magic token. Dumping page for debugging:${NC}" | |
| echo "$LOGIN_PAGE" | head -30 | |
| return 1 | |
| fi | |
| log "Extracted magic token: ${MAGIC}" | |
| # Step 3: Determine the POST URL | |
| # The form action is "/" which is relative to the firewall host | |
| FIREWALL_BASE=$(echo "$EFFECTIVE_URL" | grep -o 'http://[^/]*') | |
| if [ -z "$FIREWALL_BASE" ]; then | |
| FIREWALL_BASE="$FIREWALL_URL" | |
| fi | |
| POST_URL="${FIREWALL_BASE}/" | |
| log "Posting login to: ${POST_URL}" | |
| # Step 4: Submit the login form | |
| RESPONSE=$(curl -s -L --max-time 10 \ | |
| -d "4Tredir=${REDIR}" \ | |
| -d "magic=${MAGIC}" \ | |
| -d "username=${USERNAME}" \ | |
| -d "password=${PASSWORD}" \ | |
| "$POST_URL" 2>/dev/null) | |
| # Step 5: Check if login succeeded | |
| # After successful login, the firewall returns a keepalive page with a JS redirect. | |
| # Extract the keepalive URL so we can ping it to keep the session alive. | |
| KEEPALIVE_URL=$(echo "$RESPONSE" | grep -o 'http://172\.16\.[0-9.]*:1000/keepalive?[^"'"'"' <]*' | head -1) | |
| if [ -n "$KEEPALIVE_URL" ]; then | |
| log "${GREEN}Login successful! Keepalive URL: ${KEEPALIVE_URL}${NC}" | |
| LAST_KEEPALIVE=$(date +%s) | |
| # Give the firewall a moment to activate the session | |
| sleep 3 | |
| # Verify internet actually works now | |
| if check_internet; then | |
| log "${GREEN}Internet is now available.${NC}" | |
| else | |
| log "${YELLOW}Keepalive received but internet check not passing yet. Will retry on next cycle.${NC}" | |
| fi | |
| return 0 | |
| else | |
| # No keepalive URL found - check if maybe internet works anyway | |
| sleep 2 | |
| if check_internet; then | |
| log "${GREEN}Login successful! Internet is now available.${NC}" | |
| return 0 | |
| fi | |
| log "${RED}Login attempt failed. Check your credentials.${NC}" | |
| echo "$RESPONSE" | head -20 | |
| return 1 | |
| fi | |
| } | |
| # --- Main Loop --- | |
| log "${GREEN}Firewall auto-login script started.${NC}" | |
| log "Checking connectivity every ${CHECK_INTERVAL} seconds..." | |
| if [ "$USERNAME" = "YOUR_STUDENT_ID" ] || [ "$PASSWORD" = "YOUR_PASSWORD" ]; then | |
| log "${RED}ERROR: Please edit this script and set your USERNAME and PASSWORD.${NC}" | |
| exit 1 | |
| fi | |
| ping_keepalive() { | |
| if [ -n "$KEEPALIVE_URL" ]; then | |
| NOW=$(date +%s) | |
| ELAPSED=$(( NOW - LAST_KEEPALIVE )) | |
| if [ "$ELAPSED" -ge "$KEEPALIVE_INTERVAL" ]; then | |
| curl -s --max-time 5 "$KEEPALIVE_URL" > /dev/null 2>&1 | |
| LAST_KEEPALIVE=$NOW | |
| log "Pinged keepalive to maintain session." | |
| fi | |
| fi | |
| } | |
| while true; do | |
| if check_internet; then | |
| log "${GREEN}Internet is working.${NC}" | |
| ping_keepalive | |
| else | |
| do_login | |
| fi | |
| sleep "$CHECK_INTERVAL" | |
| done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment