-
Notifications
You must be signed in to change notification settings - Fork 1
/
skywifi.go
103 lines (92 loc) · 2.42 KB
/
skywifi.go
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
package main
import (
"errors"
"fmt"
"log"
"net/http"
"net/http/cookiejar"
"net/url"
"regexp"
"strings"
"github.com/PuerkitoBio/goquery"
"github.com/kkyr/fig"
"github.com/nylone/cloudflare-ddns/utils"
)
const (
configFile = "config/skywifi.yml"
)
var (
v4Regex = regexp.MustCompile(`([\d.]+)`)
v6Regex = regexp.MustCompile(`([a-f0-9:]+:+)+[a-f0-9]+`)
// http client able to work with cookies
jar, _ = cookiejar.New(nil)
client = &http.Client{
Jar: jar,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
cfg config // config file mappings
)
type config struct {
Username string `fig:"username" validate:"required"`
Password string `fig:"password" validate:"required"`
Router string `fig:"router" validate:"required"`
}
// Loads the config file
func init() {
err := fig.Load(&cfg, fig.File(configFile))
if err != nil {
panic(err)
}
}
// GetIPs returns public IP address of the machine from the specified endpoint
func GetIPs(loadV4, loadV6 bool) (string, string, error) {
// authenticate to webserver
v := url.Values{}
v.Set("username", cfg.Username)
v.Add("password", cfg.Password)
request, err := http.NewRequest("POST", fmt.Sprint("http://", cfg.Router, "/check.jst"), strings.NewReader(v.Encode()))
if err != nil {
return "", "", err
}
response, err := client.Do(request)
if err != nil {
return "", "", err
}
defer response.Body.Close()
if len(response.Cookies()) > 0 {
// request connection info page
var doc *goquery.Document
request, err = http.NewRequest("GET", fmt.Sprint("http://", cfg.Router, "/network_setup.jst"), nil)
if err != nil {
return "", "", err
}
response, err = client.Do(request)
if err != nil {
return "", "", err
}
defer response.Body.Close()
doc, err = goquery.NewDocumentFromReader(response.Body)
if err != nil {
log.Fatal(err)
}
// scrape and find ipv4 and ipv6 addresses from the document
var ipv4, ipv6 = "", ""
if loadV4 {
ipv4 = doc.Find("#wanip4").Next().Text()
ipv4 = v4Regex.FindAllString(ipv4, 1)[0]
}
if loadV6 {
routerIpv6 := doc.Find("#wanip6").Next().Text()
routerIpv6 = v6Regex.FindAllString(routerIpv6, 1)[0]
ipv6, err = utils.FindOwnInterfaceIP(routerIpv6, 64)
if err != nil {
return "", "", err
}
}
return ipv4, ipv6, nil
} else {
return "", "", errors.New("login attempt failed for user " + cfg.Username + " on router " + cfg.Router)
}
}