山野匹夫 大佬有话说 : 2020-3-29 20:10:39
关于ocserv 认证表单问题,付费求帮助
本帖最后由 山野匹夫 于 2020-3-29 20:15 编辑
之前发过帖子没有找到答案
偶然看到一个大佬5年前也研究过
正常配置的ocserv 在anyconnect客户端中是这样的2个页面
https://s1.ax1x.com/2020/03/29/GZeEVK.png
需要实现的效果是下面这样账号密码在1个页面
https://s1.ax1x.com/2020/03/29/GZZLD0.png
以下是大佬搞的hack认证表单,让用户名密码在一次提示中输入,并能正常认证使用
能看明白的大佬PM下联系方式,我TG:@gs166 付费求帮助
// ocservFront project main.go
package main
import (
"bufio"
"bytes"
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"regexp"
"strings"
)
const authFormOld = `<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="扶墙" type="auth-request">
<version who="sg">0.1(1)</version>
<auth id="main">
<message>Please enter your username</message>
<form method="post" action="/auth">
<input type="text" name="username" label="Username:" />
</form></auth>
</config-auth>`
const authFormNew = `<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="扶墙" type="auth-request">
<version who="sg">0.1(1)</version>
<auth id="main">
<message>Please enter your username</message>
<form method="post" action="/auth">
<input type="text" name="username" label="Username:" />
<input type="password" name="password" label="Password:" />
</form></auth>
</config-auth>`
var authUserPassRE = regexp.MustCompile("<auth><username>(.*?)</username><password>(.*?)</password></auth>")
var 扶墙CookieRE = regexp.MustCompile("web扶墙context=(.*?);")
func main() {
//@todo load config from file
cert, _ := tls.LoadX509KeyPair("/Users/horsley/Backup/ssl/ihorsley.com.crt", "/Users/horsley/Backup/ssl/ihorsley.com.key")
var cfg tls.Config
cfg.Certificates = []tls.Certificate{cert}
l, err := tls.Listen("tcp", ":15443", &cfg) //@todo load config from file
if err != nil {
log.Println("listen error:", err)
os.Exit(1)
}
defer l.Close()
for {
conn, err := l.Accept()
if err != nil {
log.Println("accept error:", err)
continue
}
go func(clientConn net.Conn) {
log.Println("conn process start")
defer clientConn.Close()
//@todo load config from file
remoteConn, err := tls.Dial("tcp", "vps9.ihorsley.com:443", nil) //remote can be unix cleartext socket of ocserv
if err != nil {
log.Println("connect upstream error:", err)
return
}
defer remoteConn.Close()
扶墙Cookie := make(chan string, 1)
go func() { //remote => client
hackRemoteResponse(clientConn, remoteConn, 扶墙Cookie)
io.Copy(clientConn, remoteConn)
}()
//client => remote
hackClientRequest(clientConn, remoteConn, 扶墙Cookie)
io.Copy(remoteConn, clientConn)
log.Println("conn process done")
}(conn)
}
}
//hackClientRequest
//hack auth by resend both user and pass form and cookie
func hackClientRequest(clientConn, remoteConn net.Conn, 扶墙Cookie chan string) {
reader := bufio.NewReader(clientConn)
for { //client req hacking
req, err := http.ReadRequest(reader)
if err != nil {
log.Println("ReadRequest from client conn err:", err)
return
}
if req.URL.Path == "/auth" {
var buf bytes.Buffer
_, err = buf.ReadFrom(req.Body)
req.Body.Close()
if err != nil {
log.Println("read request body from client conn err:", err)
return
}
req.Body = ioutil.NopCloser(bytes.NewReader(buf.Bytes()))
log.Println("3. second req, auth req, do first sending")
req.Write(remoteConn)
//waiting for cookie
ck := <-扶墙Cookie
log.Println("5. got cookie, resend auth req with cookie")
req.Header.Set("Cookie", fmt.Sprintf("web扶墙context=%s;", ck))
req.Body = ioutil.NopCloser(bytes.NewReader(buf.Bytes()))
req.Write(remoteConn)
log.Println("6. resend done, hack finish, going to do regular io.Copy")
break
} else {
log.Println("1. first req, pass")
req.Write(remoteConn)
}
}
}
//hackRemoteResponse
//hack auth by change auth form and drop the first cookie resp
func hackRemoteResponse(clientConn, remoteConn net.Conn, 扶墙Cookie chan string) {
reader := bufio.NewReader(remoteConn)
for { //remote resp hacking
resp, err := http.ReadResponse(reader, nil)
if err != nil {
log.Println("ReadResponse from remote conn err:", err)
return
}
if resp.ContentLength == len(authFormOld) { //hack auth form
log.Println("2. first resp, hack resp auth form")
resp.Body.Close()
resp.ContentLength = int64(len(authFormNew))
resp.Body = ioutil.NopCloser(strings.NewReader(authFormNew))
} else if ck := resp.Header.Get("Set-Cookie"); ck != "" && 扶墙CookieRE.MatchString(ck) { //get context cookie
log.Println("4. second resp, grep cookie, resp hacking finish")
if m := 扶墙CookieRE.FindStringSubmatch(ck); m != nil && m != "" {
扶墙Cookie <- m
//log.Println("get 扶墙 cookie:", m)
break
}
}
err = resp.Write(clientConn)
if err != nil {
log.Println("write to client conn err:", err)
return
}
}
}
山野匹夫 大佬有话说 :
来个老司机
gamerenzz 大佬有话说 :
同关注这个,我希望ocserv的客户端,不用第三方,保存用户名和密码,不用每次都输入,网上找到一个,但是不知道怎么用,楼主可以看看 ,权限原因,地址发不了,在v2ex上
同求高人,ocserv 客户端,自动保存用户名和密码 (不用第三方客户端实现)
山野匹夫 大佬有话说 :
gamerenzz 大佬有话说 : 2020-4-3 11:02
同关注这个,我希望ocserv的客户端,不用第三方,保存用户名和密码,不用每次都输入,网上找到一个,但是不 …
https://www.v2ex.com/t/195064
你说的是这个大佬吧,上面的表单就是他的
如果不是请回复链接后缀我瞅瞅
gamerenzz 大佬有话说 :
山野匹夫 大佬有话说 : 2020-4-3 11:39
你说的是这个大佬吧,上面的表单就是他的
如果不是请回复链接后缀我瞅瞅 …
对,就是他的,不过不懂这个