Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ACME implementation #62

Merged
merged 1 commit into from
Apr 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,32 @@ Create a `config.json` under the root directory of the program:
```json
{
"listen": ":36712",
"cert": "/home/ubuntu/my_cert.crt",
"key": "/home/ubuntu/my_key.crt",
"obfs": "AMOGUS",
"acme": {
"domains": [
"your.domain.com"
],
"email": "hacker@gmail.com"
},
"obfs": "fuck me till the daylight",
"up_mbps": 100,
"down_mbps": 100
}
```

A TLS certificate is required on the server side. It does not have to be valid and trusted, but in that case the clients
need additional configuration.
Hysteria requires a TLS certificate. You can either get a trusted TLS certificate from Let's Encrypt automatically using
the built-in ACME integration, or provide it yourself. It does not have to be valid and trusted, but in that case the
clients need additional configuration. To use your own existing TLS certificate, refer to this config:

```json
{
"listen": ":36712",
"cert": "/home/ubuntu/my.crt",
"key": "/home/ubuntu/my.key",
"obfs": "fuck me till the daylight",
"up_mbps": 100,
"down_mbps": 100
}
```

The (optional) `obfs` option obfuscates the protocol using the provided password, so that it is not apparent that this
is Hysteria/QUIC, which could be useful for bypassing DPI blocking or QoS. If the passwords of the server and client do
Expand Down Expand Up @@ -78,7 +94,7 @@ Same as the server side, create a `config.json` under the root directory of the
```json
{
"server": "example.com:36712",
"obfs": "AMOGUS",
"obfs": "fuck me till the daylight",
"up_mbps": 10,
"down_mbps": 50,
"socks5": {
Expand Down Expand Up @@ -121,8 +137,19 @@ Proxy Server: AWS US West Oregon (us-west-2)
```json5
{
"listen": ":36712", // Listen address
"cert": "/home/ubuntu/my_cert.crt", // Cert file
"key": "/home/ubuntu/my_key.crt", // Key file
"acme": {
"domains": [
"your.domain.com",
"another.domain.net"
], // Domains for the ACME cert
"email": "hacker@gmail.com", // Registration email, optional but recommended
"disable_http": false, // Disable HTTP challenges
"disable_tlsalpn": false, // Disable TLS-ALPN challenges
"alt_http_port": 8080, // Alternate port for HTTP challenges
"alt_tlsalpn_port": 4433 // Alternate port for TLS-ALPN challenges
},
"cert": "/home/ubuntu/my_cert.crt", // Cert file, mutually exclusive with the ACME options above
"key": "/home/ubuntu/my_key.crt", // Key file, mutually exclusive with the ACME options above
"up_mbps": 100, // Max upload Mbps per client
"down_mbps": 100, // Max download Mbps per client
"disable_udp": false, // Disable UDP support
Expand All @@ -141,6 +168,11 @@ Proxy Server: AWS US West Oregon (us-west-2)
}
```

#### ACME

Only HTTP and TLS-ALPN challenges are currently supported (no DNS challenges). Make sure your TCP ports 80/443 are
accessible respectively.

#### External authentication integration

If you are a commercial proxy provider, you may want to connect Hysteria to your own authentication backend.
Expand Down
39 changes: 35 additions & 4 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,31 @@ Hysteria 是专门针对恶劣网络环境进行优化的 TCP/UDP 转发和代
```json
{
"listen": ":36712",
"cert": "/home/ubuntu/my_cert.crt",
"key": "/home/ubuntu/my_key.crt",
"obfs": "AMOGUS",
"acme": {
"domains": [
"your.domain.com"
],
"email": "hacker@gmail.com"
},
"obfs": "fuck me till the daylight",
"up_mbps": 100,
"down_mbps": 100
}
```

服务端需要一个 TLS 证书,但未必一定要是有效、可信的。(只是在这种情况下客户端需要进行额外的配置)
服务端需要一个 TLS 证书。 你可以让 Hysteria 内置的 ACME 尝试自动从 Let's Encrypt 为你的服务器签发一个证书,也可以自己提供。
证书未必一定要是有效、可信的,但在这种情况下客户端需要进行额外的配置。要使用自己的 TLS 证书,参考这个配置:

```json
{
"listen": ":36712",
"cert": "/home/ubuntu/my.crt",
"key": "/home/ubuntu/my.key",
"obfs": "fuck me till the daylight",
"up_mbps": 100,
"down_mbps": 100
}
```

可选的 `obfs` 选项使用提供的密码对协议进行混淆,这样协议就不容易被检测出是 Hysteria/QUIC,可以用来绕过针对性的 DPI 屏蔽或者 QoS。
如果服务端和客户端的密码不匹配就不能建立连接,因此这也可以作为一个简单的密码验证。对于更高级的验证方案请见下文 `auth`。
Expand Down Expand Up @@ -109,6 +125,17 @@ Hysteria 是专门针对恶劣网络环境进行优化的 TCP/UDP 转发和代
```json5
{
"listen": ":36712", // 监听地址
"acme": {
"domains": [
"your.domain.com",
"another.domain.net"
], // ACME 证书域名
"email": "hacker@gmail.com", // 注册邮箱,可选,推荐
"disable_http": false, // 禁用 HTTP 验证方式
"disable_tlsalpn": false, // 禁用 TLS-ALPN 验证方式
"alt_http_port": 8080, // HTTP 验证方式替代端口
"alt_tlsalpn_port": 4433 // TLS-ALPN 验证方式替代端口
},
"cert": "/home/ubuntu/my_cert.crt", // 证书
"key": "/home/ubuntu/my_key.crt", // 证书密钥
"up_mbps": 100, // 单客户端最大上传速度
Expand All @@ -129,6 +156,10 @@ Hysteria 是专门针对恶劣网络环境进行优化的 TCP/UDP 转发和代
}
```

#### ACME

目前仅支持 HTTP 与 TLS-ALPN 验证方式,不支持 DNS 验证。对于两种方式请分别确保 TCP 80/443 端口能够被访问。

#### 接入外部验证

如果你是商业代理服务提供商,可以这样把 Hysteria 接入到自己的验证后端:
Expand Down
18 changes: 18 additions & 0 deletions cmd/acme.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import (
"crypto/tls"
"github.com/caddyserver/certmagic"
)

func acmeTLSConfig(domains []string, email string, disableHTTP bool, disableTLSALPN bool,
altHTTPPort int, altTLSALPNPort int) (*tls.Config, error) {
certmagic.DefaultACME.Agreed = true
certmagic.DefaultACME.Email = email
certmagic.DefaultACME.DisableHTTPChallenge = disableHTTP
certmagic.DefaultACME.DisableTLSALPNChallenge = disableTLSALPN
certmagic.DefaultACME.AltHTTPPort = altHTTPPort
certmagic.DefaultACME.AltTLSALPNPort = altTLSALPNPort
cfg := certmagic.NewDefault()
return cfg.TLSConfig(), cfg.ManageSync(domains)
}
14 changes: 11 additions & 3 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@ const (
)

type serverConfig struct {
Listen string `json:"listen"`
Listen string `json:"listen"`
ACME struct {
Domains []string `json:"domains"`
Email string `json:"email"`
DisableHTTPChallenge bool `json:"disable_http"`
DisableTLSALPNChallenge bool `json:"disable_tlsalpn"`
AltHTTPPort int `json:"alt_http_port"`
AltTLSALPNPort int `json:"alt_tlsalpn_port"`
} `json:"acme"`
CertFile string `json:"cert"`
KeyFile string `json:"key"`
// Optional below
Expand All @@ -40,8 +48,8 @@ func (c *serverConfig) Check() error {
if len(c.Listen) == 0 {
return errors.New("no listen address")
}
if len(c.CertFile) == 0 || len(c.KeyFile) == 0 {
return errors.New("TLS cert or key not provided")
if len(c.ACME.Domains) == 0 && (len(c.CertFile) == 0 || len(c.KeyFile) == 0) {
return errors.New("ACME domain or TLS cert not provided")
}
if c.UpMbps < 0 || c.DownMbps < 0 {
return errors.New("invalid speed")
Expand Down
44 changes: 31 additions & 13 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,36 @@ import (

func server(config *serverConfig) {
logrus.WithField("config", config.String()).Info("Server configuration loaded")
// Load cert
cert, err := tls.LoadX509KeyPair(config.CertFile, config.KeyFile)
if err != nil {
logrus.WithFields(logrus.Fields{
"error": err,
"cert": config.CertFile,
"key": config.KeyFile,
}).Fatal("Failed to load the certificate")
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
NextProtos: []string{tlsProtocolName},
MinVersion: tls.VersionTLS13,
// Load TLS config
var tlsConfig *tls.Config
if len(config.ACME.Domains) > 0 {
// ACME mode
tc, err := acmeTLSConfig(config.ACME.Domains, config.ACME.Email,
config.ACME.DisableHTTPChallenge, config.ACME.DisableTLSALPNChallenge,
config.ACME.AltHTTPPort, config.ACME.AltTLSALPNPort)
if err != nil {
logrus.WithFields(logrus.Fields{
"error": err,
}).Fatal("Failed to get a certificate with ACME")
}
tc.NextProtos = []string{tlsProtocolName}
tc.MinVersion = tls.VersionTLS13
tlsConfig = tc
} else {
// Local cert mode
cert, err := tls.LoadX509KeyPair(config.CertFile, config.KeyFile)
if err != nil {
logrus.WithFields(logrus.Fields{
"error": err,
"cert": config.CertFile,
"key": config.KeyFile,
}).Fatal("Failed to load the certificate")
}
tlsConfig = &tls.Config{
Certificates: []tls.Certificate{cert},
NextProtos: []string{tlsProtocolName},
MinVersion: tls.VersionTLS13,
}
}
// QUIC config
quicConfig := &quic.Config{
Expand All @@ -55,6 +72,7 @@ func server(config *serverConfig) {
}
// Auth
var authFunc func(addr net.Addr, auth []byte, sSend uint64, sRecv uint64) (bool, string)
var err error
switch authMode := config.Auth.Mode; authMode {
case "", "none":
logrus.Warn("No authentication configured")
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.14

require (
github.com/LiamHaworth/go-tproxy v0.0.0-20190726054950-ef7efd7f24ed
github.com/caddyserver/certmagic v0.13.0
github.com/elazarl/goproxy v0.0.0-20200426045556-49ad98f6dac1
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2
github.com/hashicorp/golang-lru v0.5.4
Expand Down
Loading