utils.py 3.27 KB
Newer Older
rgaudin's avatar
rgaudin committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4 nu

import re
import subprocess

from flask_babel import gettext

# seconds to expire registration after
# synced with cron job launching clean_iptables.sh
REGISTRATION_TIMEOUT = 15 * 60

APPLE_HOSTS = [
    "captive.apple.com",
    "appleiphonecell.com",
    "*.apple.com.edgekey.net",
    "gsp1.apple.com",
    "apple.com",
    "www.apple.com",
]

MICROSOFT_HOSTS = [
    "ipv6.msftncsi.com",
    "detectportal.firefox.com",
    "ipv6.msftncsi.com.edgesuite.net",
    "www.msftncsi.com",
    "www.msftncsi.com.edgesuite.net",
    "www.msftconnecttest.com",
    "www.msn.com",
    "teredo.ipv6.microsoft.com",
    "teredo.ipv6.microsoft.com.nsatc.net",
    "ctldl.windowsupdate.com",
]

GOOGLE_HOSTS = [
    "clients3.google.com",
    "mtalk.google.com",
    "alt7-mtalk.google.com",
    "alt6-mtalk.google.com",
    "connectivitycheck.android.com",
    "connectivitycheck.gstatic.com",
    "developers.google.cn",
]

LINUX_HOSTS = ["connectivity-check.ubuntu.com", "nmcheck.gnome.org"]

FIREFOX_HOSTS = ["detectportal.firefox.com"]


def has_internet():
    try:
        with open("/tmp/has_internet", "r") as f:
            return f.read().strip() == "yes"
    except Exception:
        return False


def is_active(ip_addr):
    conntrack_ps = subprocess.run(
        ["/usr/sbin/conntrack", "-L"], capture_output=True, text=True
    )
    for line in conntrack_ps.stdout.splitlines():
        if "ESTABLISHED" in line and ip_addr in line:
            return True
    return False


def fw_allow_host(ip_addr):
    """ add ip_addr to iptable's CAPTIVE_PASSLIST to skip portal """
    passlist_ps = subprocess.run(
        ["/usr/bin/sudo", "/usr/sbin/iptables", "-t", "nat", "-nL", "CAPTIVE_PASSLIST"],
        capture_output=True,
        text=True,
    )
    passlist = [
        re.split(r"\s+", line)[3]
        for line in passlist_ps.stdout.splitlines()
        if "--" in line
    ]
    if ip_addr in passlist:
        return
    subprocess.run(
        [
            "/usr/bin/sudo",
            "/usr/sbin/iptables",
            "-t",
            "nat",
            "-I",
            "CAPTIVE_PASSLIST",
            "1",
            "-s",
            str(ip_addr),
            "-j",
            "ACCEPT",
        ]
    )


def is_google_request(request):
    return request.path == "/gen_204" or request.path == "/generate_204"


def is_apple_request(request):
    return request.host in APPLE_HOSTS


def is_microsoft_request(request):
    return request.host in MICROSOFT_HOSTS


def is_microsoft_ncsi_request(request):
    return request.host == "www.msftncsi.com" and request.path == "/ncsi.txt"


def is_linux_request(request):
    return request.host in LINUX_HOSTS


def is_nmcheck_request(request):
    return (
        request.host == "nmcheck.gnome.org"
        and request.path == "/check_network_status.txt"
    )


def is_ubuntu_request(request):
    return request.host == "connectivity-check.ubuntu.com"


def is_firefox_request(request):
    return request.host in FIREFOX_HOSTS and request.path == "/success.txt"


def colored_status(status):
    return '<span class="{status}">{verbose}</span>'.format(
        status=status,
        verbose={"online": gettext("Online"), "offline": gettext("Offline")}.get(
            status
        ),
    )