update
This commit is contained in:
152
cmd/https_reverse_proxy/https_reverse_proxy.go
Normal file
152
cmd/https_reverse_proxy/https_reverse_proxy.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/darkit/goproxy"
|
||||
"github.com/darkit/goproxy/config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 解析命令行参数
|
||||
var (
|
||||
listenAddr = flag.String("listen", ":443", "HTTPS监听地址")
|
||||
httpAddr = flag.String("http", ":80", "HTTP监听地址,用于重定向到HTTPS")
|
||||
targetAddr = flag.String("target", "http://localhost:8080", "目标服务地址")
|
||||
certFile = flag.String("cert", "server.crt", "TLS证书文件")
|
||||
keyFile = flag.String("key", "server.key", "TLS私钥文件")
|
||||
autoRedirect = flag.Bool("redirect", true, "自动将HTTP请求重定向到HTTPS")
|
||||
insecureSkipVerify = flag.Bool("insecure", false, "跳过目标HTTPS验证")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
// 检查证书和私钥文件
|
||||
if !fileExists(*certFile) || !fileExists(*keyFile) {
|
||||
log.Printf("证书或私钥文件不存在: %s, %s", *certFile, *keyFile)
|
||||
if *autoRedirect {
|
||||
log.Printf("将只启动HTTP服务")
|
||||
} else {
|
||||
log.Fatalf("无法启动HTTPS服务,请提供有效的证书和私钥文件")
|
||||
}
|
||||
}
|
||||
|
||||
// 创建配置
|
||||
cfg := config.DefaultConfig()
|
||||
|
||||
// 配置反向代理
|
||||
cfg.ReverseProxy = true // 启用反向代理模式
|
||||
cfg.ListenAddr = *listenAddr // HTTPS监听地址
|
||||
cfg.TargetAddr = *targetAddr // 目标地址
|
||||
cfg.DecryptHTTPS = true // 启用HTTPS
|
||||
cfg.TLSCert = *certFile // 证书文件
|
||||
cfg.TLSKey = *keyFile // 私钥文件
|
||||
cfg.PreserveClientIP = true // 保留客户端IP
|
||||
cfg.AddXForwardedFor = true // 添加X-Forwarded-For头
|
||||
cfg.InsecureSkipVerify = *insecureSkipVerify // 是否跳过目标HTTPS验证
|
||||
|
||||
// 创建代理实例
|
||||
proxy := goproxy.New(&goproxy.Options{
|
||||
Config: cfg,
|
||||
})
|
||||
|
||||
// 创建HTTPS服务器
|
||||
httpsServer := &http.Server{
|
||||
Addr: *listenAddr,
|
||||
Handler: proxy,
|
||||
TLSConfig: &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
},
|
||||
}
|
||||
|
||||
// 创建HTTP重定向服务器
|
||||
var httpServer *http.Server
|
||||
if *autoRedirect {
|
||||
httpServer = &http.Server{
|
||||
Addr: *httpAddr,
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// 构建重定向URL
|
||||
host := r.Host
|
||||
// 如果Host包含端口,去除端口
|
||||
if h, _, err := net.SplitHostPort(host); err == nil {
|
||||
host = h
|
||||
}
|
||||
// 构建HTTPS URL
|
||||
target := "https://" + host
|
||||
// 如果HTTPS端口不是443,添加端口
|
||||
if *listenAddr != ":443" {
|
||||
_, port, _ := net.SplitHostPort(*listenAddr)
|
||||
if port != "" && port != "443" {
|
||||
target = "https://" + host + ":" + port
|
||||
}
|
||||
}
|
||||
// 添加路径和查询参数
|
||||
target += r.URL.Path
|
||||
if r.URL.RawQuery != "" {
|
||||
target += "?" + r.URL.RawQuery
|
||||
}
|
||||
// 重定向
|
||||
http.Redirect(w, r, target, http.StatusMovedPermanently)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
// 优雅退出
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
// 启动HTTPS服务器
|
||||
if fileExists(*certFile) && fileExists(*keyFile) {
|
||||
go func() {
|
||||
fmt.Printf("HTTPS反向代理启动在 %s,转发到 %s\n", *listenAddr, *targetAddr)
|
||||
if err := httpsServer.ListenAndServeTLS(*certFile, *keyFile); err != nil && err != http.ErrServerClosed {
|
||||
log.Printf("HTTPS服务器启动失败: %v\n", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// 启动HTTP重定向服务器
|
||||
if *autoRedirect && httpServer != nil {
|
||||
go func() {
|
||||
fmt.Printf("HTTP重定向服务启动在 %s\n", *httpAddr)
|
||||
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
log.Printf("HTTP服务器启动失败: %v\n", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待退出信号
|
||||
<-quit
|
||||
fmt.Println("服务器正在关闭...")
|
||||
|
||||
// 关闭服务器
|
||||
if httpServer != nil {
|
||||
if err := httpServer.Close(); err != nil {
|
||||
log.Printf("HTTP服务器关闭失败: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
if fileExists(*certFile) && fileExists(*keyFile) {
|
||||
if err := httpsServer.Close(); err != nil {
|
||||
log.Printf("HTTPS服务器关闭失败: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("服务器已关闭")
|
||||
}
|
||||
|
||||
// 检查文件是否存在
|
||||
func fileExists(filename string) bool {
|
||||
info, err := os.Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return !info.IsDir()
|
||||
}
|
Reference in New Issue
Block a user