diff --git a/docs/zh-cn/README.md b/docs/zh-cn/README.md index 74cc313..7cb99ac 100644 --- a/docs/zh-cn/README.md +++ b/docs/zh-cn/README.md @@ -12,24 +12,16 @@ see more: https://github.com/genshen/wssocks#server-side. ## 使用示例:客户端 -1. 登录 n.ustb.edu.cn; - -2. 打开浏览器的 DevTools (以chrome为例), 获得当前页面(登录成功的n.ustb.edu.cn)的cookie, 主要是名为`wengine_vpn_ticket`的cookie; -![](asserts/get-cookie.png) -**声明**: 服务器端不会保存任何用户信息, 所有的信息(如cookie)均保存中用户客户端主机中。 - -3. 打开命令行,执行如下命令: +1. 打开命令行,执行如下命令,运行客户端: > 下面命令中, `wssocks-ustb`可执行程序均指代包含`wssocks-plugin-ustb`插件功能的`wssocks`程序. ```bash - # macOS, linux - USTB_VPN=ON VPN_COOKIE=wengine_vpn_ticket=b28f9aabf8d4f3dd wssocks-ustb client --addr :1080 --remote ws://proxy.gensh.me - # windows powershell - $env:USTB_VPN='ON'; $env:VPN_COOKIE='wengine_vpn_ticket=b28f9aabf8d4f3dd'; wssocks-ustb client --addr :1080 --remote ws://proxy.gensh.me + wssocks-ustb client --addr :1080 --remote ws://proxy.gensh.me --vpn-enable ``` - 这里,设置了两个环境变量`USTB_VPN`与`VPN_COOKIE`, 分别说明当前环境是需要通过n.ustb.edu.cn连接校内网络的以及设置n.ustb.edu.cn网站的cookie。 - 此外,客户端本地监听地址为`:1080`(即0.0.0.0:1080), 服务器端地址为`ws://proxy.gensh.me`。 + 以上命令通过启用`--vpn-enable`选项启用通过vpn连接校内到网络。 + 随后, 要求输入vpn的用户名和密码登录`n.ustb.edu.cn`以获取其cookie (用户名和密码也可以在命令中通过`--vpn-usernam`和`--vpn-password`选项指定)。 + 此外,客户端默认本地监听地址为`:1080`(即0.0.0.0:1080), 服务器端地址为`ws://proxy.gensh.me`。 -4. 设置代理 +2. 设置代理 使用socks代理客户端软件(如mac系统的全局代理功能), 设置代理地址。 ![](asserts/mac-proxy.png) 在mac中,勾选**socks代理**选项框, 并填入代理服务器的地址及端口(即wssocks客户端本地监听地址及端口),保存生效。 diff --git a/go.mod b/go.mod index 7f31560..c9c0297 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,9 @@ module github.com/genshen/wssocks-plugin-ustb go 1.12 require ( - github.com/genshen/cmds v0.0.0-20181110071553-72099a07a84d - github.com/genshen/wssocks v0.1.0 + github.com/genshen/cmds v0.0.0-20190410131841-986519260a65 + github.com/genshen/wssocks v0.2.0 + github.com/gorilla/websocket v1.4.0 + github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c + golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5 // indirect ) diff --git a/go.sum b/go.sum index a5f6a56..6cf47ae 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,14 @@ -github.com/genshen/cmds v0.0.0-20181110071553-72099a07a84d h1:tlQcG70GfH1gr3DXjQqY0s6Y3zSfpcW64frduwMIUog= -github.com/genshen/cmds v0.0.0-20181110071553-72099a07a84d/go.mod h1:Uo2P6VGNS7t++sjm8vO2AqK/AB2v/favOgOZB984Z3o= -github.com/genshen/wssocks v0.1.0 h1:8weru0xsyyezlxLK6VF47BWku2CUcEXnDvsBRsCsd4U= -github.com/genshen/wssocks v0.1.0/go.mod h1:N7XkxXk+/rRVqcxiAw4fRhwsb1cMSy6EpzaHiyQFvTA= +github.com/genshen/cmds v0.0.0-20190410131841-986519260a65 h1:RYKhlk6k5qpQBZVaSi+azOINxxJRujYMGHVAdMstw+o= +github.com/genshen/cmds v0.0.0-20190410131841-986519260a65/go.mod h1:Uo2P6VGNS7t++sjm8vO2AqK/AB2v/favOgOZB984Z3o= +github.com/genshen/wssocks v0.2.0 h1:jHmXm2qMaWVblXo9awJCHdTDnroypdVDOHQzi2dHZ2Q= +github.com/genshen/wssocks v0.2.0/go.mod h1:W02tOrZ61oQgnc5redw4yNzUxdN8yo2aQ3/+fzj2Li4= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0= +github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/segmentio/ksuid v1.0.2 h1:9yBfKyw4ECGTdALaF09Snw3sLJmYIX6AbPJrAy6MrDc= github.com/segmentio/ksuid v1.0.2/go.mod h1:BXuJDr2byAiHuQaQtSKoXh1J0YmUDurywOXgB2w+OSU= +golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5 h1:bselrhR0Or1vomJZC8ZIjWtbDmn9OYFLX5Ik9alpJpE= +golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vpn_plugin/auto_login.go b/vpn_plugin/auto_login.go new file mode 100644 index 0000000..7da0522 --- /dev/null +++ b/vpn_plugin/auto_login.go @@ -0,0 +1,45 @@ +package vpn_plugin + +import ( + "errors" + "fmt" + "net/http" + "net/url" + "strings" +) + +// auto login vpn and get cookie +func vpnLogin(address, uname, passwd string) ([]*http.Cookie, error) { + form := url.Values{ + "auth_type": {"local"}, + "sms_code": {""}, + "username": {uname}, + "password": {passwd}, + } + + hc := http.Client{ + // disable redirection + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse + }, + } + req, err := http.NewRequest("POST", address, strings.NewReader(form.Encode())) // // todo missing http. + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + + if resp, err := hc.Do(req); err != nil { + return nil, err + } else { + defer resp.Body.Close() + cookies := resp.Cookies() + // return cookies or error. + if len(cookies) == 0 { + return nil, errors.New(fmt.Sprintf("no cookie while auto login to %s ", address)) + } else { + return cookies, nil + } + } +} diff --git a/vpn_plugin/vpn.go b/vpn_plugin/vpn.go index 4f26717..429c1a2 100644 --- a/vpn_plugin/vpn.go +++ b/vpn_plugin/vpn.go @@ -1,9 +1,16 @@ package vpn_plugin import ( + "bufio" + "errors" "fmt" + "github.com/genshen/cmds" + "github.com/genshen/wssocks/client" + "github.com/gorilla/websocket" + "github.com/howeyc/gopass" "net" "net/http" + "net/http/cookiejar" "net/url" "os" "strings" @@ -11,16 +18,69 @@ import ( const USTBVpnHost = "n.ustb.edu.cn" const USTBVpnHttpScheme = "http" +const USTBVpnLoginUrl = USTBVpnHttpScheme + "://" + USTBVpnHost + "/do-login" const USTBVpnWSScheme = "ws" -type UstbVpn struct{} +type UstbVpn struct { + enable bool + username string + password string + targetUrl string +} + +// create a UstbVpn instance, and add necessary command options to client sub-command. +func NewUstbVpn() *UstbVpn { + vpn := UstbVpn{} + // add more command options for client sub-command. + if ok, clientCmd := cmds.Find(client.CommandNameClient); ok { + clientCmd.FlagSet.BoolVar(&vpn.enable, "vpn-enable", false, `enable USTB vpn feature.`) + clientCmd.FlagSet.StringVar(&vpn.username, "vpn-username", "", `username to login vpn.`) + clientCmd.FlagSet.StringVar(&vpn.password, "vpn-password", "", `password to login vpn.`) + clientCmd.FlagSet.StringVar(&vpn.targetUrl, "vpn-login-url", USTBVpnLoginUrl, `address to login vpn.`) + } + return &vpn +} -func (v *UstbVpn) BeforeRequest(url *url.URL, header http.Header) { - if os.Getenv("USTB_VPN") == "" { - return +func (v *UstbVpn) BeforeRequest(dialer *websocket.Dialer, url *url.URL, header http.Header) error { + if !v.enable { + return nil } - header.Add("Cookie", os.Getenv("VPN_COOKIE")) + // read username and password if they are empty. + if v.username == "" { + reader := bufio.NewReader(os.Stdin) + fmt.Print("Enter username: ") + if text, err := reader.ReadString('\n'); err != nil { + return errors.New("Whoops! Error while reading username:" + err.Error()) + } else { + v.username = strings.TrimSuffix(text,"\n") + } + } + if v.password == "" { + fmt.Print("Enter Password: ") + if bytePassword, err := gopass.GetPasswd(); err != nil { // error + return errors.New("Whoops! Error while parsing password:" + err.Error()) + } else { + v.password = string(bytePassword) + } + } + + // change target url. vpnUrl(url) + // add cookie + if cookies, err := vpnLogin(v.targetUrl, v.username, v.password); err != nil { + return err + } else { + if jar, err := cookiejar.New(nil); err != nil { + return err + } else { + dialer.Jar = jar + cookieUrl := *url + // replace url scheme "wss" to "https" and "ws"to "http" + cookieUrl.Scheme = strings.Replace(cookieUrl.Scheme, "ws", "http", 1) + dialer.Jar.SetCookies(&cookieUrl, cookies) + return nil + } + } } func vpnUrl(u *url.URL) { diff --git a/wssocks-ustb/main.go b/wssocks-ustb/main.go index e048413..80ddab9 100644 --- a/wssocks-ustb/main.go +++ b/wssocks-ustb/main.go @@ -4,7 +4,6 @@ import ( "github.com/genshen/cmds" "github.com/genshen/wssocks-plugin-ustb/vpn_plugin" "github.com/genshen/wssocks/client" - _ "github.com/genshen/wssocks/client" _ "github.com/genshen/wssocks/server" "log" //_ "github.com/genshen/wssocks/version" @@ -13,8 +12,8 @@ import ( // initialize USTB vpn (n.ustb.edu.cn) plugin func init() { - vpn := vpn_plugin.UstbVpn{} - client.AddPluginRedirect(&vpn) + vpn := vpn_plugin.NewUstbVpn() + client.AddPluginRedirect(vpn) } func main() { diff --git a/wssocks-ustb/version/version.go b/wssocks-ustb/version/version.go index 1480ceb..3ba2305 100644 --- a/wssocks-ustb/version/version.go +++ b/wssocks-ustb/version/version.go @@ -7,7 +7,7 @@ import ( "github.com/genshen/wssocks/wss" ) -const VERSION = "0.1.0" +const VERSION = "0.2.0" var versionCommand = &cmds.Command{ Name: "version", @@ -36,6 +36,6 @@ func (v *version) Run() error { fmt.Printf("protocol version\t %d\n", wss.VersionCode) fmt.Println("This is a socks5 proxy which allows you to visit internal network in USTB.") fmt.Println("github https://github.com/genshen/wssocks-plugin-ustb") - fmt.Println("based on https://github.com/genshen/ws-socks") + fmt.Println("based on https://github.com/genshen/wssocks") return nil }