mirror of
https://github.com/bjdgyc/anylink.git
synced 2025-08-08 03:10:32 +08:00
@@ -67,6 +67,14 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
||||
data["admin_user"] = adminUser
|
||||
data["expires_at"] = expiresAt
|
||||
|
||||
ck := &http.Cookie{
|
||||
Name: "jwt",
|
||||
Value: tokenString,
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
}
|
||||
http.SetCookie(w, ck)
|
||||
|
||||
RespSucess(w, data)
|
||||
}
|
||||
|
||||
@@ -76,13 +84,15 @@ func authMiddleware(next http.Handler) http.Handler {
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET,POST,OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "*")
|
||||
if r.Method == http.MethodOptions {
|
||||
// 正式环境不支持 OPTIONS
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
route := mux.CurrentRoute(r)
|
||||
name := route.GetName()
|
||||
// fmt.Println("bb", r.URL.Path, name)
|
||||
if utils.InArrStr([]string{"login", "index", "static", "debug"}, name) {
|
||||
if utils.InArrStr([]string{"login", "index", "static"}, name) {
|
||||
// 不进行鉴权
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
@@ -93,6 +103,12 @@ func authMiddleware(next http.Handler) http.Handler {
|
||||
if jwtToken == "" {
|
||||
jwtToken = r.FormValue("jwt")
|
||||
}
|
||||
if jwtToken == "" {
|
||||
cc, err := r.Cookie("jwt")
|
||||
if err == nil {
|
||||
jwtToken = cc.Value
|
||||
}
|
||||
}
|
||||
data, err := GetJwtData(jwtToken)
|
||||
if err != nil || base.Cfg.AdminUser != fmt.Sprint(data["admin_user"]) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/arl/statsviz"
|
||||
"github.com/bjdgyc/anylink/base"
|
||||
"github.com/bjdgyc/anylink/dbdata"
|
||||
"github.com/bjdgyc/anylink/pkg/utils"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -20,6 +21,13 @@ var UiData embed.FS
|
||||
func StartAdmin() {
|
||||
|
||||
r := mux.NewRouter()
|
||||
// 所有路由添加安全头
|
||||
r.Use(func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
utils.SetSecureHeader(w)
|
||||
next.ServeHTTP(w, req)
|
||||
})
|
||||
})
|
||||
r.Use(authMiddleware)
|
||||
r.Use(handlers.CompressHandler)
|
||||
|
||||
|
@@ -3,5 +3,5 @@ package base
|
||||
const (
|
||||
APP_NAME = "AnyLink"
|
||||
// app版本号
|
||||
APP_VER = "0.9.4"
|
||||
APP_VER = "0.10.1"
|
||||
)
|
||||
|
65
server/base/mod.go
Normal file
65
server/base/mod.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
procModulesPath = "/proc/modules"
|
||||
inContainerKey = "ANYLINK_IN_CONTAINER"
|
||||
)
|
||||
|
||||
var (
|
||||
inContainer = false
|
||||
modMap = map[string]struct{}{}
|
||||
)
|
||||
|
||||
func initMod() {
|
||||
container := os.Getenv(inContainerKey)
|
||||
if container == "true" {
|
||||
inContainer = true
|
||||
}
|
||||
log.Println("inContainer", inContainer)
|
||||
|
||||
file, err := os.Open(procModulesPath)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("[ERROR] Problem with open file: %s", err)
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
scanner := bufio.NewScanner(file)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
for scanner.Scan() {
|
||||
splited := strings.Split(scanner.Text(), " ")
|
||||
if len(splited[0]) > 0 {
|
||||
modMap[splited[0]] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CheckModOrLoad(mod string) {
|
||||
log.Println("CheckModOrLoad", mod)
|
||||
|
||||
if _, ok := modMap[mod]; ok {
|
||||
return
|
||||
}
|
||||
|
||||
if inContainer {
|
||||
err := fmt.Errorf("Linux modules %s is not loaded, please run `modprobe %s`", mod, mod)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cmdstr := fmt.Sprintln("modprobe", mod)
|
||||
|
||||
cmd := exec.Command("sh", "-c", cmdstr)
|
||||
b, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Println(string(b))
|
||||
panic(err)
|
||||
}
|
||||
}
|
@@ -4,6 +4,7 @@ func Start() {
|
||||
execute()
|
||||
initCfg()
|
||||
initLog()
|
||||
initMod()
|
||||
}
|
||||
|
||||
func Test() {
|
||||
|
@@ -1,2 +1,2 @@
|
||||
客户端软件需放置在files目录内,
|
||||
如需要帮助请加QQ群:567510628
|
||||
如需要帮助请加QQ群:567510628 、739072205
|
@@ -8,6 +8,7 @@
|
||||
<RestrictPreferenceCaching>false</RestrictPreferenceCaching>
|
||||
<RestrictTunnelProtocols>IPSec</RestrictTunnelProtocols>
|
||||
<BypassDownloader>true</BypassDownloader>
|
||||
<AutoUpdate UserControllable="false">false</AutoUpdate>
|
||||
<WindowsVPNEstablishment>AllowRemoteUsers</WindowsVPNEstablishment>
|
||||
<LinuxVPNEstablishment>AllowRemoteUsers</LinuxVPNEstablishment>
|
||||
<CertEnrollmentPin>pinAllowed</CertEnrollmentPin>
|
||||
@@ -20,15 +21,19 @@
|
||||
</ExtendedKeyUsage>
|
||||
</CertificateMatch>
|
||||
|
||||
<BackupServerList>
|
||||
<HostAddress>localhost</HostAddress>
|
||||
</BackupServerList>
|
||||
</ClientInitialization>
|
||||
|
||||
<ServerList>
|
||||
|
||||
<HostEntry>
|
||||
<HostName>VPN Server</HostName>
|
||||
<HostName>VPN</HostName>
|
||||
<HostAddress>localhost</HostAddress>
|
||||
</HostEntry>
|
||||
|
||||
<HostEntry>
|
||||
<HostName>VPN2</HostName>
|
||||
<HostAddress>localhost2</HostAddress>
|
||||
</HostEntry>
|
||||
|
||||
</ServerList>
|
||||
</AnyConnectProfile>
|
@@ -41,6 +41,6 @@ iptables_nat = true
|
||||
|
||||
|
||||
#客户端显示详细错误信息(线上环境慎开启)
|
||||
display_error = false
|
||||
display_error = true
|
||||
|
||||
|
||||
|
@@ -2,10 +2,13 @@ package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bjdgyc/anylink/base"
|
||||
@@ -20,10 +23,13 @@ func startDtls() {
|
||||
return
|
||||
}
|
||||
|
||||
certificate, err := selfsign.GenerateSelfSigned()
|
||||
// rsa 兼容 open connect
|
||||
priv, _ := rsa.GenerateKey(rand.Reader, 2048)
|
||||
certificate, err := selfsign.SelfSign(priv)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logf := logging.NewDefaultLoggerFactory()
|
||||
logf.Writer = base.GetBaseLw()
|
||||
// logf.DefaultLogLevel = logging.LogLevelTrace
|
||||
@@ -34,12 +40,17 @@ func startDtls() {
|
||||
|
||||
config := &dtls.Config{
|
||||
Certificates: []tls.Certificate{certificate},
|
||||
InsecureSkipVerify: true,
|
||||
ExtendedMasterSecret: dtls.DisableExtendedMasterSecret,
|
||||
CipherSuites: []dtls.CipherSuiteID{dtls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
|
||||
LoggerFactory: logf,
|
||||
MTU: BufferSize,
|
||||
SessionStore: sessStore,
|
||||
CipherSuites: func() []dtls.CipherSuiteID {
|
||||
var cs = []dtls.CipherSuiteID{}
|
||||
for _, vv := range dtlsCipherSuites {
|
||||
cs = append(cs, vv)
|
||||
}
|
||||
return cs
|
||||
}(),
|
||||
LoggerFactory: logf,
|
||||
MTU: BufferSize,
|
||||
SessionStore: sessStore,
|
||||
ConnectContextMaker: func() (context.Context, func()) {
|
||||
return context.WithTimeout(context.Background(), 5*time.Second)
|
||||
},
|
||||
@@ -98,3 +109,23 @@ func (ms *sessionStore) Get(key []byte) (dtls.Session, error) {
|
||||
func (ms *sessionStore) Del(key []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 客户端和服务端映射 X-DTLS12-CipherSuite
|
||||
var dtlsCipherSuites = map[string]dtls.CipherSuiteID{
|
||||
// "ECDHE-ECDSA-AES256-GCM-SHA384": dtls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
// "ECDHE-ECDSA-AES128-GCM-SHA256": dtls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
"ECDHE-RSA-AES256-GCM-SHA384": dtls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
"ECDHE-RSA-AES128-GCM-SHA256": dtls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
}
|
||||
|
||||
func checkDtls12Ciphersuite(ciphersuite string) string {
|
||||
csArr := strings.Split(ciphersuite, ":")
|
||||
|
||||
for _, v := range csArr {
|
||||
if _, ok := dtlsCipherSuites[v]; ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
// 返回默认值
|
||||
return "ECDHE-RSA-AES128-GCM-SHA256"
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
@@ -49,7 +50,7 @@ func LinkAuth(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
// fmt.Printf("%+v \n", cr)
|
||||
setCommonHeader(w)
|
||||
// setCommonHeader(w)
|
||||
if cr.Type == "logout" {
|
||||
// 退出删除session信息
|
||||
if cr.SessionToken != "" {
|
||||
@@ -154,10 +155,12 @@ func tplRequest(typ int, w io.Writer, data RequestData) {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.Contains(data.Banner, "\n") {
|
||||
// 替换xml文件的换行符
|
||||
data.Banner = strings.ReplaceAll(data.Banner, "\n", "
")
|
||||
if data.Banner != "" {
|
||||
buf := new(bytes.Buffer)
|
||||
xml.EscapeText(buf, []byte(data.Banner))
|
||||
data.Banner = buf.String()
|
||||
}
|
||||
|
||||
t, _ := template.New("auth_complete").Parse(auth_complete)
|
||||
_ = t.Execute(w, data)
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ package handler
|
||||
import (
|
||||
"encoding/xml"
|
||||
"log"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
@@ -42,28 +41,6 @@ type macAddressList struct {
|
||||
MacAddress string `xml:"mac-address"`
|
||||
}
|
||||
|
||||
func setCommonHeader(w http.ResponseWriter) {
|
||||
// Content-Length Date 默认已经存在
|
||||
w.Header().Set("Server", "AnyLinkOpenSource")
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.Header().Set("Cache-Control", "no-store,no-cache")
|
||||
w.Header().Set("Pragma", "no-cache")
|
||||
w.Header().Set("Transfer-Encoding", "chunked")
|
||||
w.Header().Set("Connection", "keep-alive")
|
||||
w.Header().Set("X-Frame-Options", "deny")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("Content-Security-Policy", "default-src 'none'")
|
||||
w.Header().Set("X-Permitted-Cross-Domain-Policies", "none")
|
||||
w.Header().Set("Referrer-Policy", "no-referrer")
|
||||
w.Header().Set("Clear-Site-Data", "cache,cookies,storage")
|
||||
w.Header().Set("Cross-Origin-Embedder-Policy", "require-corp")
|
||||
w.Header().Set("Cross-Origin-Opener-Policy", "same-origin")
|
||||
w.Header().Set("Cross-Origin-Resource-Policy", "same-origin")
|
||||
w.Header().Set("X-XSS-Protection", "0")
|
||||
w.Header().Set("X-Aggregate-Auth", "1")
|
||||
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
|
||||
}
|
||||
|
||||
func execCmd(cmdStrs []string) error {
|
||||
for _, cmdStr := range cmdStrs {
|
||||
cmd := exec.Command("sh", "-c", cmdStr)
|
||||
|
@@ -13,7 +13,7 @@ func LinkHome(w http.ResponseWriter, r *http.Request) {
|
||||
// fmt.Println(r.RemoteAddr)
|
||||
// hu, _ := httputil.DumpRequest(r, true)
|
||||
// fmt.Println("DumpHome: ", string(hu))
|
||||
w.Header().Set("Server", "AnyLinkOpenSource")
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
connection := strings.ToLower(r.Header.Get("Connection"))
|
||||
userAgent := strings.ToLower(r.UserAgent())
|
||||
if connection == "close" && (strings.Contains(userAgent, "anyconnect") || strings.Contains(userAgent, "openconnect")) {
|
||||
|
@@ -22,22 +22,29 @@ func checkTun() {
|
||||
defer ifce.Close()
|
||||
|
||||
// 测试ip命令
|
||||
cmdstr := fmt.Sprintf("ip link set dev %s up mtu %s multicast off", ifce.Name(), "1399")
|
||||
err = execCmd([]string{cmdstr})
|
||||
base.CheckModOrLoad("tun")
|
||||
|
||||
cmdstr1 := fmt.Sprintf("ip link set dev %s up mtu %s multicast off", ifce.Name(), "1399")
|
||||
err = execCmd([]string{cmdstr1})
|
||||
if err != nil {
|
||||
base.Fatal("testTun err: ", err)
|
||||
}
|
||||
//开启服务器转发
|
||||
// 开启服务器转发
|
||||
if err := execCmd([]string{"sysctl -w net.ipv4.ip_forward=1"}); err != nil {
|
||||
base.Error(err)
|
||||
base.Fatal(err)
|
||||
}
|
||||
if base.Cfg.IptablesNat {
|
||||
//添加NAT转发规则
|
||||
// 添加NAT转发规则
|
||||
ipt, err := iptables.New()
|
||||
if err != nil {
|
||||
base.Error(err)
|
||||
base.Fatal(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 修复 rockyos nat 不生效
|
||||
base.CheckModOrLoad("iptable_filter")
|
||||
base.CheckModOrLoad("iptable_nat")
|
||||
|
||||
natRule := []string{"-s", base.Cfg.Ipv4CIDR, "-o", base.Cfg.Ipv4Master, "-j", "MASQUERADE"}
|
||||
forwardRule := []string{"-j", "ACCEPT"}
|
||||
if natExists, _ := ipt.Exists("nat", "POSTROUTING", natRule...); !natExists {
|
||||
@@ -65,7 +72,10 @@ func LinkTun(cSess *sessdata.ConnSession) error {
|
||||
// log.Printf("Interface Name: %s\n", ifce.Name())
|
||||
cSess.SetIfName(ifce.Name())
|
||||
|
||||
cmdstr1 := fmt.Sprintf("ip link set dev %s up mtu %d multicast off", ifce.Name(), cSess.Mtu)
|
||||
// 通过 ip link show 查看 alias 信息
|
||||
|
||||
cmdstr1 := fmt.Sprintf("ip link set dev %s up mtu %d multicast off alias %s.%s", ifce.Name(), cSess.Mtu,
|
||||
cSess.Group.Name, cSess.Username)
|
||||
cmdstr2 := fmt.Sprintf("ip addr add dev %s local %s peer %s/32",
|
||||
ifce.Name(), base.Cfg.Ipv4Gateway, cSess.IpAddr)
|
||||
err = execCmd([]string{cmdstr1, cmdstr2})
|
||||
|
@@ -92,6 +92,10 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
base.Debug(cSess.IpAddr, cSess.MacHw, sess.Username, mobile)
|
||||
|
||||
// 检测密码套件
|
||||
dtlsCiphersuite := checkDtls12Ciphersuite(r.Header.Get("X-Dtls12-Ciphersuite"))
|
||||
base.Trace("dtlsCiphersuite", dtlsCiphersuite)
|
||||
|
||||
// 压缩
|
||||
if cmpName, ok := cSess.SetPickCmp("cstp", r.Header.Get("X-Cstp-Accept-Encoding")); ok {
|
||||
HttpSetHeader(w, "X-CSTP-Content-Encoding", cmpName)
|
||||
@@ -164,7 +168,7 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) {
|
||||
HttpSetHeader(w, "X-DTLS-Port", dtlsPort)
|
||||
HttpSetHeader(w, "X-DTLS-DPD", fmt.Sprintf("%d", cstpDpd))
|
||||
HttpSetHeader(w, "X-DTLS-Keepalive", fmt.Sprintf("%d", cstpKeepalive))
|
||||
HttpSetHeader(w, "X-DTLS12-CipherSuite", "ECDHE-ECDSA-AES128-GCM-SHA256")
|
||||
HttpSetHeader(w, "X-DTLS12-CipherSuite", dtlsCiphersuite)
|
||||
|
||||
HttpSetHeader(w, "X-CSTP-License", "accept")
|
||||
HttpSetHeader(w, "X-CSTP-Routing-Filtering-Ignore", "false")
|
||||
@@ -234,7 +238,11 @@ func SetPostAuthXml(g *dbdata.Group, w http.ResponseWriter) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
HttpSetHeader(w, "X-CSTP-Post-Auth-XML", result.String())
|
||||
xmlAuth := ""
|
||||
for _, v := range strings.Split(result.String(), "\n") {
|
||||
xmlAuth += strings.TrimSpace(v)
|
||||
}
|
||||
HttpSetHeader(w, "X-CSTP-Post-Auth-XML", xmlAuth)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -33,13 +33,14 @@ func checkMacvtap() {
|
||||
|
||||
ifName := "anylinkMacvtap"
|
||||
// 加载 macvtap
|
||||
cmdstr0 := fmt.Sprintln("modprobe -i macvtap")
|
||||
base.CheckModOrLoad("macvtap")
|
||||
|
||||
// 开启主网卡混杂模式
|
||||
cmdstr1 := fmt.Sprintf("ip link set dev %s promisc on", base.Cfg.Ipv4Master)
|
||||
// 测试 macvtap 功能
|
||||
cmdstr2 := fmt.Sprintf("ip link add link %s name %s type macvtap mode bridge", base.Cfg.Ipv4Master, ifName)
|
||||
cmdstr3 := fmt.Sprintf("ip link del %s", ifName)
|
||||
err := execCmd([]string{cmdstr0, cmdstr1, cmdstr2, cmdstr3})
|
||||
err := execCmd([]string{cmdstr1, cmdstr2, cmdstr3})
|
||||
if err != nil {
|
||||
base.Fatal(err)
|
||||
}
|
||||
@@ -54,7 +55,8 @@ func LinkMacvtap(cSess *sessdata.ConnSession) error {
|
||||
cSess.SetIfName(ifName)
|
||||
|
||||
cmdstr1 := fmt.Sprintf("ip link add link %s name %s type macvtap mode bridge", base.Cfg.Ipv4Master, ifName)
|
||||
cmdstr2 := fmt.Sprintf("ip link set dev %s up mtu %d address %s", ifName, cSess.Mtu, cSess.MacHw)
|
||||
cmdstr2 := fmt.Sprintf("ip link set dev %s up mtu %d address %s alias %s.%s", ifName, cSess.Mtu, cSess.MacHw,
|
||||
cSess.Group.Name, cSess.Username)
|
||||
err := execCmd([]string{cmdstr1, cmdstr2})
|
||||
if err != nil {
|
||||
base.Error(err)
|
||||
|
@@ -3,6 +3,7 @@ package handler
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"github.com/bjdgyc/anylink/base"
|
||||
@@ -101,11 +102,17 @@ func logAuditBatch() {
|
||||
|
||||
// 解析IP包的数据
|
||||
func logAudit(userName string, pl *sessdata.Payload) {
|
||||
defer putPayload(pl)
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
base.Error("logAudit is panic: ", err, "\n", string(debug.Stack()), "\n", pl.Data)
|
||||
}
|
||||
putPayload(pl)
|
||||
}()
|
||||
|
||||
if !(pl.LType == sessdata.LTypeIPData && pl.PType == 0x00) {
|
||||
return
|
||||
}
|
||||
|
||||
ipProto := waterutil.IPv4Protocol(pl.Data)
|
||||
// 访问协议
|
||||
var accessProto uint8
|
||||
@@ -118,11 +125,15 @@ func logAudit(userName string, pl *sessdata.Payload) {
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
// IP报文只包含头部信息时, 则打印LOG,并退出
|
||||
ipPl := waterutil.IPv4Payload(pl.Data)
|
||||
if len(ipPl) < 4 {
|
||||
base.Error("ipPl len < 4", ipPl, pl.Data)
|
||||
return
|
||||
}
|
||||
ipPort := (uint16(ipPl[2]) << 8) | uint16(ipPl[3])
|
||||
ipSrc := waterutil.IPv4Source(pl.Data)
|
||||
ipDst := waterutil.IPv4Destination(pl.Data)
|
||||
ipPort := waterutil.IPv4DestinationPort(pl.Data)
|
||||
|
||||
b := getByte51()
|
||||
key := *b
|
||||
copy(key[:16], ipSrc)
|
||||
@@ -178,7 +189,6 @@ func logAudit(userName string, pl *sessdata.Payload) {
|
||||
AccessProto: accessProto,
|
||||
Info: info,
|
||||
}
|
||||
|
||||
select {
|
||||
case logBatch.LogChan <- audit:
|
||||
default:
|
||||
|
@@ -29,7 +29,7 @@ func onTCP(payload []byte) (uint8, string) {
|
||||
}
|
||||
|
||||
func sniNewParser(b []byte) (uint8, string) {
|
||||
if len(b) < 2 || b[0] != 0x16 || b[1] != 0x03 {
|
||||
if len(b) < 6 || b[0] != 0x16 || b[1] != 0x03 {
|
||||
return acc_proto_tcp, ""
|
||||
}
|
||||
rest := b[5:]
|
||||
|
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/bjdgyc/anylink/base"
|
||||
"github.com/bjdgyc/anylink/dbdata"
|
||||
"github.com/bjdgyc/anylink/pkg/utils"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pires/go-proxyproto"
|
||||
)
|
||||
@@ -53,7 +54,6 @@ func startTls() {
|
||||
base.Trace("GetCertificate", chi.ServerName)
|
||||
return dbdata.GetCertificateBySNI(chi.ServerName)
|
||||
},
|
||||
// InsecureSkipVerify: true,
|
||||
}
|
||||
srv := &http.Server{
|
||||
Addr: addr,
|
||||
@@ -86,6 +86,14 @@ func startTls() {
|
||||
|
||||
func initRoute() http.Handler {
|
||||
r := mux.NewRouter()
|
||||
// 所有路由添加安全头
|
||||
r.Use(func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
utils.SetSecureHeader(w)
|
||||
next.ServeHTTP(w, req)
|
||||
})
|
||||
})
|
||||
|
||||
r.HandleFunc("/", LinkHome).Methods(http.MethodGet)
|
||||
r.HandleFunc("/", LinkAuth).Methods(http.MethodPost)
|
||||
r.HandleFunc("/CSCOSSLC/tunnel", LinkTunnel).Methods(http.MethodConnect)
|
||||
|
32
server/pkg/utils/secure_header.go
Normal file
32
server/pkg/utils/secure_header.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package utils
|
||||
|
||||
import "net/http"
|
||||
|
||||
// SetSecureHeader 设置安全的header头
|
||||
// https://blog.csdn.net/liwan09/article/details/130248003
|
||||
// https://zhuanlan.zhihu.com/p/335165168
|
||||
func SetSecureHeader(w http.ResponseWriter) {
|
||||
// Content-Length Date 默认已经存在
|
||||
w.Header().Set("Server", "AnyLinkOpenSource")
|
||||
// w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
// w.Header().Set("Transfer-Encoding", "chunked")
|
||||
w.Header().Set("X-Aggregate-Auth", "1")
|
||||
|
||||
w.Header().Set("Cache-Control", "no-store,no-cache")
|
||||
w.Header().Set("Pragma", "no-cache")
|
||||
w.Header().Set("Connection", "keep-alive")
|
||||
w.Header().Set("X-Frame-Options", "SAMEORIGIN")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("X-Download-Options", "noopen")
|
||||
w.Header().Set("Content-Security-Policy", "default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:; frame-ancestors 'self'; base-uri 'self'; block-all-mixed-content")
|
||||
w.Header().Set("X-Permitted-Cross-Domain-Policies", "none")
|
||||
w.Header().Set("Referrer-Policy", "same-origin")
|
||||
w.Header().Set("Cross-Origin-Embedder-Policy", "require-corp")
|
||||
w.Header().Set("Cross-Origin-Opener-Policy", "same-origin")
|
||||
w.Header().Set("Cross-Origin-Resource-Policy", "same-origin")
|
||||
w.Header().Set("X-XSS-Protection", "1;mode=block")
|
||||
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
|
||||
|
||||
// w.Header().Set("Clear-Site-Data", "cache,cookies,storage")
|
||||
|
||||
}
|
Reference in New Issue
Block a user