mirror of
https://github.com/cmz0228/hysteria-dev.git
synced 2025-06-08 05:19:53 +00:00
Merge pull request #44 from tobyxdd/wip-http-auth
HTTP external auth implementation
This commit is contained in:
commit
67f1e469d7
38
README.md
38
README.md
@ -125,7 +125,7 @@ Proxy Server: AWS US West Oregon (us-west-2)
|
||||
"acl": "my_list.acl", // See ACL below
|
||||
"obfs": "AMOGUS", // Obfuscation password
|
||||
"auth": { // Authentication
|
||||
"mode": "password", // Mode, only supports "password" and "none" for now
|
||||
"mode": "password", // Mode, supports "password" "none" and "external" for now
|
||||
"config": {
|
||||
"password": "yubiyubi"
|
||||
}
|
||||
@ -136,6 +136,42 @@ Proxy Server: AWS US West Oregon (us-west-2)
|
||||
}
|
||||
```
|
||||
|
||||
#### External authentication integration
|
||||
|
||||
If you are a commercial proxy provider, you may want to connect Hysteria to your own authentication backend.
|
||||
|
||||
```json5
|
||||
{
|
||||
// ...
|
||||
"auth": {
|
||||
"mode": "external",
|
||||
"config": {
|
||||
"http": "https://api.example.com/auth" // Both HTTP and HTTPS are supported
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For the above config, Hysteria sends a POST request to `https://api.example.com/auth` upon each client's connection:
|
||||
|
||||
```json5
|
||||
{
|
||||
"addr": "111.222.111.222:52731",
|
||||
"payload": "[BASE64]", // auth or auth_str of the client
|
||||
"send": 12500000, // Negotiated server send speed for this client (Bps)
|
||||
"recv": 12500000 // Negotiated server recv speed for this client (Bps)
|
||||
}
|
||||
```
|
||||
|
||||
The endpoint must return results with HTTP status code 200 (even if the authentication failed):
|
||||
|
||||
```json5
|
||||
{
|
||||
"ok": false,
|
||||
"msg": "No idea who you are"
|
||||
}
|
||||
```
|
||||
|
||||
### Client
|
||||
|
||||
```json5
|
||||
|
40
README.zh.md
40
README.zh.md
@ -100,7 +100,7 @@ Hysteria 是专门针对恶劣网络环境(常见于卫星网络、在中国
|
||||
|
||||
## 高级用法
|
||||
|
||||
### Server
|
||||
### 服务器
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -124,7 +124,43 @@ Hysteria 是专门针对恶劣网络环境(常见于卫星网络、在中国
|
||||
}
|
||||
```
|
||||
|
||||
### Client
|
||||
#### 接入外部验证
|
||||
|
||||
如果你是商业代理服务提供商,可以这样把 Hysteria 接入到自己的验证后端:
|
||||
|
||||
```json5
|
||||
{
|
||||
// ...
|
||||
"auth": {
|
||||
"mode": "external",
|
||||
"config": {
|
||||
"http": "https://api.example.com/auth" // 支持 HTTP 和 HTTPS
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
对于上述配置,Hysteria 会把验证请求通过 HTTP POST 发送到 `https://api.example.com/auth`
|
||||
|
||||
```json5
|
||||
{
|
||||
"addr": "111.222.111.222:52731",
|
||||
"payload": "[BASE64]", // 对应客户端配置的 auth 或 auth_str 字段
|
||||
"send": 12500000, // 协商后的服务端最大发送速率 (Bps)
|
||||
"recv": 12500000 // 协商后的服务端最大接收速率 (Bps)
|
||||
}
|
||||
```
|
||||
|
||||
后端必须用 HTTP 200 状态码返回验证结果(即使验证不通过):
|
||||
|
||||
```json5
|
||||
{
|
||||
"ok": false,
|
||||
"msg": "No idea who you are"
|
||||
}
|
||||
```
|
||||
|
||||
### 客户端
|
||||
|
||||
```json5
|
||||
{
|
||||
|
@ -6,12 +6,15 @@ import (
|
||||
"github.com/lucas-clemente/quic-go/congestion"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tobyxdd/hysteria/pkg/acl"
|
||||
"github.com/tobyxdd/hysteria/pkg/auth"
|
||||
hyCongestion "github.com/tobyxdd/hysteria/pkg/congestion"
|
||||
"github.com/tobyxdd/hysteria/pkg/core"
|
||||
"github.com/tobyxdd/hysteria/pkg/obfs"
|
||||
"github.com/yosuke-furukawa/json5/encoding/json5"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func server(config *serverConfig) {
|
||||
@ -72,6 +75,22 @@ func server(config *serverConfig) {
|
||||
return false, "Wrong password"
|
||||
}
|
||||
}
|
||||
case "external":
|
||||
logrus.Info("External authentication enabled")
|
||||
var extConfig map[string]string
|
||||
err = json5.Unmarshal(config.Auth.Config, &extConfig)
|
||||
if err != nil || len(extConfig["http"]) == 0 {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"error": err,
|
||||
}).Fatal("Invalid external authentication config")
|
||||
}
|
||||
provider := &auth.HTTPAuthProvider{
|
||||
Client: &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
},
|
||||
URL: extConfig["http"],
|
||||
}
|
||||
authFunc = provider.Auth
|
||||
default:
|
||||
logrus.WithField("mode", config.Auth.Mode).Fatal("Unsupported authentication mode")
|
||||
}
|
||||
|
56
pkg/auth/http.go
Normal file
56
pkg/auth/http.go
Normal file
@ -0,0 +1,56 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type HTTPAuthProvider struct {
|
||||
Client *http.Client
|
||||
URL string
|
||||
}
|
||||
|
||||
type authReq struct {
|
||||
Addr string `json:"addr"`
|
||||
Payload []byte `json:"payload"`
|
||||
Send uint64 `json:"send"`
|
||||
Recv uint64 `json:"recv"`
|
||||
}
|
||||
|
||||
type authResp struct {
|
||||
OK bool `json:"ok"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
func (p *HTTPAuthProvider) Auth(addr net.Addr, auth []byte, sSend uint64, sRecv uint64) (bool, string) {
|
||||
jbs, err := json.Marshal(&authReq{
|
||||
Addr: addr.String(),
|
||||
Payload: auth,
|
||||
Send: sSend,
|
||||
Recv: sRecv,
|
||||
})
|
||||
if err != nil {
|
||||
return false, "Internal error"
|
||||
}
|
||||
resp, err := p.Client.Post(p.URL, "application/json", bytes.NewBuffer(jbs))
|
||||
if err != nil {
|
||||
return false, "Internal error"
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return false, "Auth endpoint error"
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false, "Auth endpoint error"
|
||||
}
|
||||
var ar authResp
|
||||
err = json.Unmarshal(data, &ar)
|
||||
if err != nil {
|
||||
return false, "Auth endpoint error"
|
||||
}
|
||||
return ar.OK, ar.Msg
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user