站点保护功能,代码优化

pull/1219/head
刘河 2018-12-30 22:36:15 +08:00
parent dc1520da1f
commit 4dad726129
10 changed files with 215 additions and 99 deletions

View File

@ -1,6 +1,12 @@
appname = httpMonitor appname = httpMonitor
#web管理端口
httpport = 8080 httpport = 8080
#启动模式dev|pro
runmode = dev runmode = dev
#web管理密码
password=123 password=123
#http监听端口
hostPort=8028 hostPort=8028
#basic auth认证用户名和密码
auth.user=test
auth.password=1234

View File

@ -178,14 +178,14 @@ func (s *Conn) SetAlive() {
} }
//从tcp报文中解析出host //从tcp报文中解析出host
func (s *Conn) GetHost() (method, address string, rb []byte, err error) { func (s *Conn) GetHost() (method, address string, rb []byte, err error, r *http.Request) {
var b [32 * 1024]byte var b [32 * 1024]byte
var n int var n int
if n, err = s.Read(b[:]); err != nil { if n, err = s.Read(b[:]); err != nil {
return return
} }
rb = b[:n] rb = b[:n]
r, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(rb))) r, err = http.ReadRequest(bufio.NewReader(bytes.NewReader(rb)))
if err != nil { if err != nil {
log.Println("解析host出错", err) log.Println("解析host出错", err)
return return

View File

@ -3,6 +3,7 @@ package lib
import ( import (
"errors" "errors"
"flag" "flag"
"github.com/astaxie/beego"
"log" "log"
"reflect" "reflect"
"strings" "strings"
@ -42,7 +43,7 @@ func InitMode() {
stop := make(chan int) stop := make(chan int)
for _, v := range strings.Split(*verifyKey, ",") { for _, v := range strings.Split(*verifyKey, ",") {
log.Println("客户端启动,连接:", *serverAddr, " 验证令牌:", v) log.Println("客户端启动,连接:", *serverAddr, " 验证令牌:", v)
go NewRPClient(*serverAddr, 2, v).Start() go NewRPClient(*serverAddr, 3, v).Start()
} }
<-stop <-stop
} else { } else {
@ -71,15 +72,19 @@ func InitFromCsv() {
} }
func newMode(mode string, bridge *Tunnel, httpPort int, tunnelTarget string, u string, p string, enCompress int, deCompress int, vkey string) interface{} { func newMode(mode string, bridge *Tunnel, httpPort int, tunnelTarget string, u string, p string, enCompress int, deCompress int, vkey string) interface{} {
if u == "" || p == "" { //如果web管理中设置了用户名和密码则覆盖配置文件
u = beego.AppConfig.String("auth.user")
p = beego.AppConfig.String("auth.password")
}
switch mode { switch mode {
case "httpServer": case "httpServer":
return NewHttpModeServer(httpPort, bridge, enCompress, deCompress, vkey) return NewHttpModeServer(httpPort, bridge, enCompress, deCompress, vkey)
case "tunnelServer": case "tunnelServer":
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessTunnel, bridge, enCompress, deCompress, vkey) return NewTunnelModeServer(httpPort, tunnelTarget, ProcessTunnel, bridge, enCompress, deCompress, vkey, u, p)
case "sock5Server": case "sock5Server":
return NewSock5ModeServer(httpPort, u, p, bridge, enCompress, deCompress, vkey) return NewSock5ModeServer(httpPort, u, p, bridge, enCompress, deCompress, vkey)
case "httpProxyServer": case "httpProxyServer":
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessHttp, bridge, enCompress, deCompress, vkey) return NewTunnelModeServer(httpPort, tunnelTarget, ProcessHttp, bridge, enCompress, deCompress, vkey, u, p)
case "udpServer": case "udpServer":
return NewUdpModeServer(httpPort, tunnelTarget, bridge, enCompress, deCompress, vkey) return NewUdpModeServer(httpPort, tunnelTarget, bridge, enCompress, deCompress, vkey)
case "webServer": case "webServer":
@ -88,7 +93,7 @@ func newMode(mode string, bridge *Tunnel, httpPort int, tunnelTarget string, u s
case "hostServer": case "hostServer":
return NewHostServer() return NewHostServer()
case "httpHostServer": case "httpHostServer":
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessHost, bridge, enCompress, deCompress, vkey) return NewTunnelModeServer(httpPort, tunnelTarget, ProcessHost, bridge, enCompress, deCompress, vkey, u, p)
} }
return nil return nil
} }
@ -97,17 +102,9 @@ func StopServer(cFlag string) error {
if v, ok := RunList[cFlag]; ok { if v, ok := RunList[cFlag]; ok {
reflect.ValueOf(v).MethodByName("Close").Call(nil) reflect.ValueOf(v).MethodByName("Close").Call(nil)
delete(RunList, cFlag) delete(RunList, cFlag)
if t := bridge.signalList[getverifyval(cFlag)]; t != nil { if *verifyKey == "" { //多客户端模式关闭相关隧道
if *verifyKey == "" { //多客户端模式重启相关隧道 bridge.DelClientSignal(cFlag)
for { bridge.DelClientTunnel(cFlag)
if t.Len() <= 0 {
break
}
t.Pop().Close()
}
delete(bridge.signalList, getverifyval(cFlag))
delete(bridge.tunnelList, getverifyval(cFlag))
}
} }
if t, err := CsvDb.GetTask(cFlag); err != nil { if t, err := CsvDb.GetTask(cFlag); err != nil {
return err return err

View File

@ -4,6 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/astaxie/beego" "github.com/astaxie/beego"
"github.com/astaxie/beego/session"
"io/ioutil" "io/ioutil"
"log" "log"
"net" "net"
@ -11,6 +12,8 @@ import (
"strings" "strings"
) )
var GlobalHostSessions *session.Manager
const ( const (
VERIFY_EER = "vkey" VERIFY_EER = "vkey"
WORK_MAIN = "main" WORK_MAIN = "main"
@ -20,6 +23,11 @@ const (
TEST_FLAG = "tst" TEST_FLAG = "tst"
CONN_TCP = "tcp" CONN_TCP = "tcp"
CONN_UDP = "udp" CONN_UDP = "udp"
Unauthorized_BYTES = `HTTP/1.1 401 Unauthorized
Content-Type: text/plain; charset=utf-8
WWW-Authenticate: Basic realm="easyProxy"
401 Unauthorized`
) )
type HttpModeServer struct { type HttpModeServer struct {
@ -44,19 +52,28 @@ func NewHttpModeServer(httpPort int, bridge *Tunnel, enCompress int, deCompress
func (s *HttpModeServer) Start() { func (s *HttpModeServer) Start() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
retry: retry:
u := beego.AppConfig.String("basic.user")
p := beego.AppConfig.String("basic.password")
if u != "" && p != "" && !checkAuth(r, u, p) {
w.Header().Set("WWW-Authenticate", `Basic realm="easyProxy""`)
w.WriteHeader(401)
w.Write([]byte("401 Unauthorized\n"))
return
}
err, conn := s.bridge.GetSignal(getverifyval(s.vKey)) err, conn := s.bridge.GetSignal(getverifyval(s.vKey))
if err != nil { if err != nil {
BadRequest(w) BadRequest(w)
return
} }
if err := s.writeRequest(r, conn); err != nil { if err := s.writeRequest(r, conn); err != nil {
log.Println(err) log.Println("write request to client error:", err)
conn.Close() conn.Close()
goto retry goto retry
return return
} }
err = s.writeResponse(w, conn) err = s.writeResponse(w, conn)
if err != nil { if err != nil {
log.Println(err) log.Println("write response error:", err)
conn.Close() conn.Close()
goto retry goto retry
return return
@ -92,7 +109,7 @@ func (s *HttpModeServer) writeResponse(w http.ResponseWriter, c *Conn) error {
} }
switch flags { switch flags {
case RES_SIGN: case RES_SIGN:
buf := make([]byte, 1024*32) buf := make([]byte, 1024*1024*32)
n, err := c.ReadFromCompress(buf, s.deCompress) n, err := c.ReadFromCompress(buf, s.deCompress)
if err != nil { if err != nil {
return err return err
@ -132,10 +149,12 @@ type TunnelModeServer struct {
listener *net.TCPListener listener *net.TCPListener
enCompress int enCompress int
deCompress int deCompress int
basicUser string
basicPassword string
vKey string vKey string
} }
func NewTunnelModeServer(httpPort int, tunnelTarget string, process process, bridge *Tunnel, enCompress int, deCompress int, vKey string) *TunnelModeServer { func NewTunnelModeServer(httpPort int, tunnelTarget string, process process, bridge *Tunnel, enCompress, deCompress int, vKey, basicUser, basicPasswd string) *TunnelModeServer {
s := new(TunnelModeServer) s := new(TunnelModeServer)
s.httpPort = httpPort s.httpPort = httpPort
s.bridge = bridge s.bridge = bridge
@ -144,6 +163,8 @@ func NewTunnelModeServer(httpPort int, tunnelTarget string, process process, bri
s.enCompress = enCompress s.enCompress = enCompress
s.deCompress = deCompress s.deCompress = deCompress
s.vKey = vKey s.vKey = vKey
s.basicUser = basicUser
s.basicPassword = basicPasswd
return s return s
} }
@ -166,6 +187,14 @@ func (s *TunnelModeServer) Start() error {
} }
return nil return nil
} }
func (s *TunnelModeServer) auth(r *http.Request, c *Conn) error {
if s.basicUser != "" && s.basicPassword != "" && !checkAuth(r, s.basicUser, s.basicPassword) {
c.Write([]byte(Unauthorized_BYTES))
c.Close()
return errors.New("401 Unauthorized")
}
return nil
}
func (s *TunnelModeServer) Close() error { func (s *TunnelModeServer) Close() error {
return s.listener.Close() return s.listener.Close()
@ -173,7 +202,12 @@ func (s *TunnelModeServer) Close() error {
//tcp隧道模式 //tcp隧道模式
func ProcessTunnel(c *Conn, s *TunnelModeServer) error { func ProcessTunnel(c *Conn, s *TunnelModeServer) error {
link := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress) link, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress)
if err != nil {
log.Println(err)
c.Close()
return err
}
if _, err := link.WriteHost(CONN_TCP, s.tunnelTarget); err != nil { if _, err := link.WriteHost(CONN_TCP, s.tunnelTarget); err != nil {
link.Close() link.Close()
c.Close() c.Close()
@ -187,12 +221,20 @@ func ProcessTunnel(c *Conn, s *TunnelModeServer) error {
//http代理模式 //http代理模式
func ProcessHttp(c *Conn, s *TunnelModeServer) error { func ProcessHttp(c *Conn, s *TunnelModeServer) error {
method, addr, rb, err := c.GetHost() method, addr, rb, err, r := c.GetHost()
if err != nil { if err != nil {
c.Close() c.Close()
return err return err
} }
link := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress) if err := s.auth(r, c); err != nil {
return err
}
link, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress)
if err != nil {
log.Println(err)
c.Close()
return err
}
if _, err := link.WriteHost(CONN_TCP, addr); err != nil { if _, err := link.WriteHost(CONN_TCP, addr); err != nil {
c.Close() c.Close()
link.Close() link.Close()
@ -211,18 +253,26 @@ func ProcessHttp(c *Conn, s *TunnelModeServer) error {
//多客户端域名代理 //多客户端域名代理
func ProcessHost(c *Conn, s *TunnelModeServer) error { func ProcessHost(c *Conn, s *TunnelModeServer) error {
method, addr, rb, err := c.GetHost() method, addr, rb, err, r := c.GetHost()
if err != nil { if err != nil {
c.Close() c.Close()
return err return err
} }
if err := s.auth(r, c); err != nil {
return err
}
host, task, err := getKeyByHost(addr) host, task, err := getKeyByHost(addr)
if err != nil { if err != nil {
c.Close() c.Close()
return err return err
} }
de, en := getCompressType(task.Compress) de, en := getCompressType(task.Compress)
link := s.bridge.GetTunnel(getverifyval(host.Vkey), en, de) link, err := s.bridge.GetTunnel(getverifyval(host.Vkey), en, de)
if err != nil {
log.Println(err)
c.Close()
return err
}
if _, err := link.WriteHost(CONN_TCP, host.Target); err != nil { if _, err := link.WriteHost(CONN_TCP, host.Target); err != nil {
c.Close() c.Close()
link.Close() link.Close()
@ -262,7 +312,7 @@ func (s *WebServer) Start() {
} }
AddTask(t) AddTask(t)
beego.BConfig.WebConfig.Session.SessionOn = true beego.BConfig.WebConfig.Session.SessionOn = true
log.Println("web管理启动访问端口为",beego.AppConfig.String("httpport")) log.Println("web管理启动访问端口为", beego.AppConfig.String("httpport"))
beego.Run() beego.Run()
} }
@ -280,6 +330,8 @@ type HostServer struct {
func (s *HostServer) Start() error { func (s *HostServer) Start() error {
return nil return nil
} }
//TODOhost模式的客户端无需指定和监听端口等此处有待优化
func NewHostServer() *HostServer { func NewHostServer() *HostServer {
s := new(HostServer) s := new(HostServer)
return s return s

View File

@ -136,7 +136,12 @@ func (s *Sock5ModeServer) doConnect(c net.Conn, command uint8) (proxyConn *Conn,
binary.Read(c, binary.BigEndian, &port) binary.Read(c, binary.BigEndian, &port)
// connect to host // connect to host
addr := net.JoinHostPort(host, strconv.Itoa(int(port))) addr := net.JoinHostPort(host, strconv.Itoa(int(port)))
client := s.bridge.GetTunnel(getverifyval(s.vKey),s.enCompress,s.deCompress) client, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress)
if err != nil {
log.Println(err)
client.Close()
return
}
s.sendReply(c, succeeded) s.sendReply(c, succeeded)
var ltype string var ltype string
if command == associateMethod { if command == associateMethod {

View File

@ -83,7 +83,6 @@ func (s *Tunnel) cliProcess(c *Conn) error {
c.conn.Close() c.conn.Close()
return err return err
} }
//TODO:暂时取消
if !verify(string(vval)) { if !verify(string(vval)) {
log.Println("当前客户端连接校验错误,关闭此客户端:", c.conn.RemoteAddr()) log.Println("当前客户端连接校验错误,关闭此客户端:", c.conn.RemoteAddr())
s.verifyError(c) s.verifyError(c)
@ -126,8 +125,10 @@ func (s *Tunnel) addList(m map[string]*list, c *Conn, cFlag string) {
} }
//新建隧道 //新建隧道
func (s *Tunnel) newChan(cFlag string) { func (s *Tunnel) newChan(cFlag string) error {
s.wait(s.signalList, cFlag) if err := s.wait(s.signalList, cFlag); err != nil {
return err
}
retry: retry:
connPass := s.signalList[cFlag].Pop() connPass := s.signalList[cFlag].Pop()
_, err := connPass.conn.Write([]byte("chan")) _, err := connPass.conn.Write([]byte("chan"))
@ -136,22 +137,25 @@ retry:
goto retry goto retry
} }
s.signalList[cFlag].Add(connPass) s.signalList[cFlag].Add(connPass)
return nil
} }
//得到一个tcp隧道 //得到一个tcp隧道
func (s *Tunnel) GetTunnel(cFlag string, en, de int) *Conn { func (s *Tunnel) GetTunnel(cFlag string, en, de int) (c *Conn, err error) {
if v, ok := s.tunnelList[cFlag]; !ok || v.Len() < 10 { //新建通道 if v, ok := s.tunnelList[cFlag]; !ok || v.Len() < 10 { //新建通道
go s.newChan(cFlag) go s.newChan(cFlag)
} }
retry: retry:
s.wait(s.tunnelList, cFlag) if err = s.wait(s.tunnelList, cFlag); err != nil {
c := s.tunnelList[cFlag].Pop() return
}
c = s.tunnelList[cFlag].Pop()
if _, err := c.wTest(); err != nil { if _, err := c.wTest(); err != nil {
c.Close() c.Close()
goto retry goto retry
} }
c.WriteCompressType(en, de) c.WriteCompressType(en, de)
return c return
} }
//得到一个通信通道 //得到一个通信通道
@ -171,14 +175,43 @@ func (s *Tunnel) ReturnSignal(conn *Conn, cFlag string) {
} }
} }
//等待 //删除通信通道
func (s *Tunnel) wait(m map[string]*list, cFlag string) { func (s *Tunnel) DelClientSignal(cFlag string) {
ticker := time.NewTicker(time.Millisecond * 100) s.delClient(cFlag, s.signalList)
}
//删除隧道
func (s *Tunnel) DelClientTunnel(cFlag string) {
s.delClient(cFlag, s.tunnelList)
}
func (s *Tunnel) delClient(cFlag string, l map[string]*list) {
if t := l[getverifyval(cFlag)]; t != nil {
for { for {
<-ticker.C if t.Len() <= 0 {
if _, ok := m[cFlag]; ok {
ticker.Stop()
break break
} }
t.Pop().Close()
}
delete(l, getverifyval(cFlag))
} }
} }
//等待
func (s *Tunnel) wait(m map[string]*list, cFlag string) error {
ticker := time.NewTicker(time.Millisecond * 100)
stop := time.After(time.Second * 10)
loop:
for {
select {
case <-ticker.C:
if _, ok := m[cFlag]; ok {
ticker.Stop()
break loop
}
case <-stop:
return errors.New("client key: " + cFlag + ",err: get client conn timeout")
}
}
return nil
}

View File

@ -57,7 +57,11 @@ func (s *UdpModeServer) Start() error {
func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) { func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
fmt.Println(addr.String()) fmt.Println(addr.String())
fmt.Println(string(data)) fmt.Println(string(data))
conn := s.bridge.GetTunnel(getverifyval(s.vKey),s.enCompress,s.deCompress) conn, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress)
if err != nil {
log.Println(err)
return
}
if _, err := conn.WriteHost(CONN_UDP, s.tunnelTarget); err != nil { if _, err := conn.WriteHost(CONN_UDP, s.tunnelTarget); err != nil {
conn.Close() conn.Close()
return return

View File

@ -5,6 +5,7 @@ import (
"bytes" "bytes"
"compress/gzip" "compress/gzip"
"crypto/md5" "crypto/md5"
"encoding/base64"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
@ -219,12 +220,12 @@ func getverifyval(vkey string) string {
} }
func verify(verifyKeyMd5 string) bool { func verify(verifyKeyMd5 string) bool {
if getverifyval(*verifyKey) == verifyKeyMd5 { if *verifyKey != "" && getverifyval(*verifyKey) == verifyKeyMd5 {
return true return true
} }
if *verifyKey == "" { if *verifyKey == "" {
for _, v := range CsvDb.Tasks { for k := range RunList {
if _, ok := RunList[v.VerifyKey]; getverifyval(v.VerifyKey) == verifyKeyMd5 && ok { if getverifyval(k) == verifyKeyMd5 {
return true return true
} }
} }
@ -237,9 +238,6 @@ func getKeyByHost(host string) (h *HostList, t *TaskList, err error) {
if strings.Contains(host, v.Host) { if strings.Contains(host, v.Host) {
h = v h = v
t, err = CsvDb.GetTask(v.Vkey) t, err = CsvDb.GetTask(v.Vkey)
if err != nil {
return
}
return return
} }
} }
@ -266,6 +264,7 @@ func GetRandomString(l int) string {
return string(result) return string(result)
} }
//通过host获取对应的ip地址
func Gethostbyname(hostname string) string { func Gethostbyname(hostname string) string {
if !DomainCheck(hostname) { if !DomainCheck(hostname) {
return hostname return hostname
@ -281,6 +280,7 @@ func Gethostbyname(hostname string) string {
return "" return ""
} }
//检查是否是域名
func DomainCheck(domain string) bool { func DomainCheck(domain string) bool {
var match bool var match bool
IsLine := "^((http://)|(https://))?([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}(/)" IsLine := "^((http://)|(https://))?([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}(/)"
@ -291,3 +291,22 @@ func DomainCheck(domain string) bool {
} }
return match return match
} }
//检查basic认证
func checkAuth(r *http.Request, user, passwd string) bool {
s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
if len(s) != 2 {
return false
}
b, err := base64.StdEncoding.DecodeString(s[1])
if err != nil {
return false
}
pair := strings.SplitN(string(b), ":", 2)
if len(pair) != 2 {
return false
}
return pair[0] == user && pair[1] == passwd
}

View File

@ -39,11 +39,11 @@
</select> </select>
</div> </div>
<div class="form-group" id="u"> <div class="form-group" id="u">
<label class="control-label">socks5</label> <label class="control-label">(socks5HTTP)</label>
<input class="form-control" type="text" name="u" placeholder="不填则无需验证"> <input class="form-control" type="text" name="u" placeholder="不填则无需验证">
</div> </div>
<div class="form-group" id="p"> <div class="form-group" id="p">
<label class="control-label">socks5</label> <label class="control-label">(socks5HTTP)</label>
<input class="form-control" type="text" name="p" placeholder="不填则无需验证"> <input class="form-control" type="text" name="p" placeholder="不填则无需验证">
</div> </div>
</form> </form>
@ -63,7 +63,7 @@
arr["tunnelServer"] = ["type", "port", "target", "compress", "tcp隧道模式提供一条tcp隧道适用于ssh、远程桌面等添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,访问公网服务器的设定端口,则相当于访问内网目标地址的目标端口"] arr["tunnelServer"] = ["type", "port", "target", "compress", "tcp隧道模式提供一条tcp隧道适用于ssh、远程桌面等添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,访问公网服务器的设定端口,则相当于访问内网目标地址的目标端口"]
arr["udpServer"] = ["type", "port", "target", "compress", "udp隧道模式提供一条udp隧道适用于dns、内网dns访问等添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后访问公网服务器的设定端口则相当于访问内网目标地址的udp目标端口"] arr["udpServer"] = ["type", "port", "target", "compress", "udp隧道模式提供一条udp隧道适用于dns、内网dns访问等添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后访问公网服务器的设定端口则相当于访问内网目标地址的udp目标端口"]
arr["sock5Server"] = ["type", "port", "compress", "u", "p", "socks5代理模式内网socks5代理配合proxifer可如同使用vpn一样访问内网设备或资源添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后在外网环境下本机配置socks5代理即访问内网设备或者资源 "] arr["sock5Server"] = ["type", "port", "compress", "u", "p", "socks5代理模式内网socks5代理配合proxifer可如同使用vpn一样访问内网设备或资源添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后在外网环境下本机配置socks5代理即访问内网设备或者资源 "]
arr["httpProxyServer"] = ["type", "port", "compress", " http代理模式内网http代理可访问内网网站添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后在外网环境下本机配置http代理即访问内网站点"] arr["httpProxyServer"] = ["type", "port", "compress", "u", "p", " http代理模式内网http代理可访问内网网站添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后在外网环境下本机配置http代理即访问内网站点"]
arr["hostServer"] = ["type", "compress", "域名分发模式使用域名代理内网服务适用于小程序开发、公众号开发、站点演示等添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后使用nginx将请求反向代理到本程序再进行域名配置即可解析"] arr["hostServer"] = ["type", "compress", "域名分发模式使用域名代理内网服务适用于小程序开发、公众号开发、站点演示等添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后使用nginx将请求反向代理到本程序再进行域名配置即可解析"]
function resetForm() { function resetForm() {

View File

@ -34,14 +34,14 @@
</select> </select>
</div> </div>
<div class="form-group" id="u"> <div class="form-group" id="u">
<label class="control-label">socks5</label> <label class="control-label">(socks5HTTP)</label>
<input class="form-control" value="{{.t.U}}" type="text" name="u" <input class="form-control" value="{{.t.U}}" type="text" name="u"
placeholder="不填则无需验证,非socks5模式不填"> placeholder="不填则无需验证">
</div> </div>
<div class="form-group" id="p"> <div class="form-group" id="p">
<label class="control-label">socks5</label> <label class="control-label">(socks5HTTP)</label>
<input class="form-control" value="{{.t.P}}" type="text" name="p" <input class="form-control" value="{{.t.P}}" type="text" name="p"
placeholder="不填则无需验证,非socks5模式不填"> placeholder="不填则无需验证">
</div> </div>
</form> </form>
</div> </div>
@ -60,7 +60,7 @@
arr["tunnelServer"] = ["type", "port", "target", "compress"] arr["tunnelServer"] = ["type", "port", "target", "compress"]
arr["udpServer"] = ["type", "port", "target", "compress"] arr["udpServer"] = ["type", "port", "target", "compress"]
arr["sock5Server"] = ["type", "port", "compress", "u", "p"] arr["sock5Server"] = ["type", "port", "compress", "u", "p"]
arr["httpProxyServer"] = ["type", "port", "compress"] arr["httpProxyServer"] = ["type", "port", "compress", "u", "p"]
arr["hostServer"] = ["type", "compress"] arr["hostServer"] = ["type", "compress"]
function resetForm() { function resetForm() {