Skip to content
This repository has been archived by the owner on Feb 29, 2024. It is now read-only.

Commit

Permalink
refactor: do some experimental restructure
Browse files Browse the repository at this point in the history
  • Loading branch information
CoolSpring8 committed Jul 4, 2020
1 parent d8a3d32 commit 7e8a7dc
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 63 deletions.
14 changes: 10 additions & 4 deletions cmd/rwppa/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// In other words, on receiving requests, they will be sent to rvpn.zju.edu.cn and corresponding results will be passed back to the browser,
// or any other HTTP-proxy-capable requesters, like clients that only utilizes HTTP protocol.

// In short, users are given the ability to browse ZJU intranet sites,
// In short, users are given the ability to access ZJU intranet sites,
// with a ZJU internet service account required, and via ZJU RVPN web portal (view rvpn.zju.edu.cn on phones to see).
// Hopefully it can replace the role of Sangfor EasyConnect, to a certain extent.

Expand All @@ -32,8 +32,8 @@ package main
import (
"fmt"

"github.com/coolspring8/rwppa/internal/login"
"github.com/coolspring8/rwppa/internal/proxy"
"github.com/coolspring8/rwppa/internal/rvpn"
)

func main() {
Expand All @@ -52,6 +52,12 @@ func main() {
if err != nil {
panic(err)
}
twfid := login.LoginRVPNWebPortal(username, password)
proxy.StartProxyServer(listenAddr, twfid)

w := rvpn.WebPortal{Username: username, Password: password}
twfid, err := w.LogIn()
if err != nil {
panic(err)
}

proxy.StartProxyServer(listenAddr, *twfid)
}
59 changes: 12 additions & 47 deletions internal/cert/cert.go
Original file line number Diff line number Diff line change
@@ -1,48 +1,31 @@
// This file was partly from https://github.com/elazarl/goproxy/blob/master/examples/goproxy-customca/cert.go
// Copyright (C) 2020 CoolSpring8

// Copyright (c) 2012 Elazar Leibovich. All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Elazar Leibovich. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

// Package cert provides operation functions on CA cert and key.
package cert

import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"io/ioutil"
"math/big"
"os"
"time"

"github.com/elazarl/goproxy"
)

// GetCA returns a CA cert, a CA key or an error in file reading or writing process.
Expand Down Expand Up @@ -114,24 +97,6 @@ func GetCA() ([]byte, []byte, error) {
return caCert, caKey, err
}

// SetCA takes CA cert and CA key, and sets up goproxy CA.
// Returns error in parsing and setting CA.
func SetCA(caCert, caKey []byte) error {
goproxyCa, err := tls.X509KeyPair(caCert, caKey)
if err != nil {
return err
}
if goproxyCa.Leaf, err = x509.ParseCertificate(goproxyCa.Certificate[0]); err != nil {
return err
}
goproxy.GoproxyCa = goproxyCa
goproxy.OkConnect = &goproxy.ConnectAction{Action: goproxy.ConnectAccept, TLSConfig: goproxy.TLSConfigFromCA(&goproxyCa)}
goproxy.MitmConnect = &goproxy.ConnectAction{Action: goproxy.ConnectMitm, TLSConfig: goproxy.TLSConfigFromCA(&goproxyCa)}
goproxy.HTTPMitmConnect = &goproxy.ConnectAction{Action: goproxy.ConnectHTTPMitm, TLSConfig: goproxy.TLSConfigFromCA(&goproxyCa)}
goproxy.RejectConnect = &goproxy.ConnectAction{Action: goproxy.ConnectReject, TLSConfig: goproxy.TLSConfigFromCA(&goproxyCa)}
return nil
}

// fileExists checks if a file exists and is not a directory.
func fileExists(filename string) bool {
info, err := os.Stat(filename)
Expand Down
23 changes: 22 additions & 1 deletion internal/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

// Package proxy provides things to set up a proxy.
package proxy

import (
"crypto/tls"
"crypto/x509"
"fmt"
"log"
"net"
Expand Down Expand Up @@ -70,7 +73,7 @@ func StartProxyServer(listenAddr, twfid string) {
if err != nil {
panic(err)
}
err = cert.SetCA(caCert, caKey)
err = SetCA(caCert, caKey)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -144,3 +147,21 @@ func StartProxyServer(listenAddr, twfid string) {
fmt.Println("Listen Address:" + listenAddr)
log.Fatal(http.ListenAndServe(listenAddr, proxy))
}

// SetCA takes CA cert and CA key, and sets up goproxy CA.
// Returns error in parsing and setting CA.
func SetCA(caCert, caKey []byte) error {
goproxyCa, err := tls.X509KeyPair(caCert, caKey)
if err != nil {
return err
}
if goproxyCa.Leaf, err = x509.ParseCertificate(goproxyCa.Certificate[0]); err != nil {
return err
}
goproxy.GoproxyCa = goproxyCa
goproxy.OkConnect = &goproxy.ConnectAction{Action: goproxy.ConnectAccept, TLSConfig: goproxy.TLSConfigFromCA(&goproxyCa)}
goproxy.MitmConnect = &goproxy.ConnectAction{Action: goproxy.ConnectMitm, TLSConfig: goproxy.TLSConfigFromCA(&goproxyCa)}
goproxy.HTTPMitmConnect = &goproxy.ConnectAction{Action: goproxy.ConnectHTTPMitm, TLSConfig: goproxy.TLSConfigFromCA(&goproxyCa)}
goproxy.RejectConnect = &goproxy.ConnectAction{Action: goproxy.ConnectReject, TLSConfig: goproxy.TLSConfigFromCA(&goproxyCa)}
return nil
}
32 changes: 21 additions & 11 deletions internal/login/login.go → internal/rvpn/rvpn.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

package login
// Package rvpn deals with things related to ZJU RVPN web portal.
package rvpn

import (
"net/http"
Expand All @@ -23,28 +24,37 @@ import (

const (
// endpointURL is where ZJU RVPN web portal's login interface locates.
// TODO: try to find out if some of the parameters are not necessary.
// TODO: find out if some of the parameters are not necessary.
endpointURL string = "https://rvpn.zju.edu.cn/por/login_psw.csp?type=cs&dev=android-phone&dev=android-phone&language=zh_CN"
)

// LoginRVPNWebPortal takes username and password, returns TWFID.
// WebPortal refers to ZJU RVPN web portal.
type WebPortal struct {
Username string // Username is ZJU network service account username.
Password string // Password is ZJU network service account password.
}

// LogIn uses username and password to get a TWFID.
// TWFID is used by the web portal for authentication.
// Incorrect or empty username and password will simply lead to a useless TWFID.
// TODO: verify before returning. throw an error if not working.
func LoginRVPNWebPortal(username, password string) string {
// TODO: verify, throw an error if not working.
func (webPortal WebPortal) LogIn() (*string, error) {
data := url.Values{}
data.Set("svpn_name", username)
data.Set("svpn_password", password)
data.Set("svpn_name", webPortal.Username)
data.Set("svpn_password", webPortal.Password)

client := &http.Client{}
r, _ := http.NewRequest("POST", endpointURL, strings.NewReader(data.Encode()))
req, err := http.NewRequest("POST", endpointURL, strings.NewReader(data.Encode()))
if err != nil {
return nil, err
}

resp, err := client.Do(r)
resp, err := client.Do(req)
if err != nil {
panic(err)
return nil, err
}

twfid := resp.Cookies()[0].Value

return twfid
return &twfid, nil
}

0 comments on commit 7e8a7dc

Please sign in to comment.