Update v0.4.2 for anylink

This commit is contained in:
Stille 2021-07-05 18:23:27 +08:00
parent 9e0abbcd95
commit 9ebc818e23
29 changed files with 268 additions and 295 deletions

View File

@ -16,7 +16,7 @@ jobs:
- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: 1.15
go-version: 1.16
id: go
- name: Check out code into the Go module directory
@ -30,7 +30,9 @@ jobs:
- name: Build
run: |
cd server
go build -v -o anylink -ldflags "-X main.COMMIT_ID=`git rev-parse HEAD`"
mkdir ui
touch ui/index.html
go build -v -o anylink -ldflags "-X main.CommitId=`git rev-parse HEAD`"
./anylink tool -v
- name: Test coverage

2
anylink/.gitignore vendored
View File

@ -1,5 +1,5 @@
# Binaries for programs and plugins
.idea/
anylink-deploy
ui
anylink-deploy.tar.gz

View File

@ -1,8 +1,7 @@
# web
FROM node:lts-alpine as builder_node
ENV VERSION 0.3.3
WORKDIR /web
ENV VERSION 0.4.2
COPY ./web /web
RUN npx browserslist@latest --update-db \
&& npm install \
@ -10,7 +9,7 @@ RUN npx browserslist@latest --update-db \
&& ls /web/ui
# server
FROM golang:alpine as builder_golang
FROM golang:1.16-alpine as builder_golang
#TODO 本地打包时使用镜像
#ENV GOPROXY=https://goproxy.io
ENV GOOS=linux
@ -21,7 +20,7 @@ COPY --from=builder_node /web/ui /anylink/server/ui
#TODO 本地打包时使用镜像
#RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
RUN apk add --no-cache git
RUN cd /anylink/server;go build -o anylink -ldflags "-X main.COMMIT_ID=$(git rev-parse HEAD)" \
RUN cd /anylink/server;go build -o anylink -ldflags "-X main.CommitId=$(git rev-parse HEAD)" \
&& /anylink/server/anylink tool -v
# anylink
@ -31,12 +30,13 @@ LABEL maintainer="github.com/bjdgyc"
ENV IPV4_CIDR="192.168.10.0/24"
WORKDIR /app
COPY --from=builder_node /web/ui /app/ui
COPY --from=builder_golang /anylink/server/anylink /app/
COPY ./server/conf /app/conf
COPY ./server/files /app/files
COPY docker_entrypoint.sh /app/
COPY ./server/conf /app/conf
COPY ./server/files /app/conf/files
#TODO 本地打包时使用镜像
#RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
RUN apk add --no-cache bash iptables \

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2020 bjdgyc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -8,7 +8,8 @@ Docker [stilleshan/anylink](https://hub.docker.com/r/stilleshan/anylink)
基于 [bjdgyc/anylink](https://github.com/bjdgyc/anylink) 项目的 docker 镜像.
## 更新
**2021-06-09** 更新`0.3.3`版 docker 镜像,新增同时支持 X86 和 ARM 架构.
- **2021-07-05** 更新`0.4.2`版 docker 镜像.
- **2021-06-09** 更新`0.3.3`版 docker 镜像,新增同时支持 X86 和 ARM 架构.
## 部署
### docker
@ -19,7 +20,6 @@ docker run -d \
--privileged=true \
-p 443:443 \
-p 8800:8800 \
-v /root/anylink/:/app/conf \
stilleshan/anylink
```

View File

@ -12,35 +12,35 @@ function RETVAL() {
#当前目录
cpath=$(pwd)
echo "编译二进制文件"
cd $cpath/server
go build -v -o anylink -ldflags "-X main.COMMIT_ID=$(git rev-parse HEAD)"
RETVAL $?
echo "编译前端项目"
cd $cpath/web
#国内可替换源加快速度
npx browserslist@latest --update-db
npm install --registry=https://registry.npm.taobao.org
npm run build --registry=https://registry.npm.taobao.org
#npm install
#npm run build
npm run build
RETVAL $?
echo "编译二进制文件"
cd $cpath/server
rm -rf ui
cp -rf $cpath/web/ui .
go build -v -o anylink -ldflags "-X main.CommitId=$(git rev-parse HEAD)"
RETVAL $?
cd $cpath
echo "整理部署文件"
deploy="anylink-deploy"
rm -rf $deploy
rm -rf $deploy ${deploy}.tar.gz
mkdir $deploy
mkdir $deploy/log
cp -r server/anylink $deploy
cp -r server/conf $deploy
cp -r server/files $deploy
cp -r server/bridge-init.sh $deploy
cp -r systemd $deploy
cp -r web/ui $deploy
tar zcvf ${deploy}.tar.gz $deploy
#注意使用root权限运行
#cd anylink-deploy

View File

@ -7,7 +7,8 @@ services:
ports:
- 443:443
- 8080:8800
volumes:
- ./app/conf:/app/conf
# volumes:
# - ./app/conf:/app/conf
# command: -c=/app/conf/server.toml
restart: always

View File

@ -16,7 +16,7 @@ case $var1 in
*)
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s "${IPV4_CIDR}" -o eth0+ -j MASQUERADE
# iptables -nL -t nat
iptables -nL -t nat
/app/anylink "$@"
;;

View File

@ -9,6 +9,7 @@ import (
"crypto/rand"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/hex"
"errors"
"math/big"
@ -70,6 +71,11 @@ func WithDNS(key crypto.PrivateKey, cn string, sans ...string) (tls.Certificate,
names = append(names, sans...)
template := x509.Certificate{
Subject: pkix.Name{
// TODO anylink
Organization: []string{cn},
OrganizationalUnit: names,
},
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth,
x509.ExtKeyUsageServerAuth,

View File

@ -1,15 +0,0 @@
# 常见问题
### anyconnect 客户端问题
> 客户端请使用群共享文件的版本,其他版本没有测试过,不保证使用正常。
>
> 添加QQ群: 567510628
### 远程桌面连接
> 本软件不支持远程桌面连接,请注意。
### 私有证书问题
> anylink 默认不支持私有证书
>
> 仅测试的话,可以通过 https://github.com/square/certstrap 生成私有的证书, 然后把CA证书放在客户端机器上即可以连接。

View File

@ -67,10 +67,11 @@ func SetSystem(w http.ResponseWriter, r *http.Request) {
hi, _ := host.Info()
l, _ := load.Avg()
data["sys"] = map[string]interface{}{
"goOs": runtime.GOOS,
"goArch": runtime.GOARCH,
"goVersion": runtime.Version(),
"goroutine": runtime.NumGoroutine(),
"goOs": runtime.GOOS,
"goArch": runtime.GOARCH,
"goVersion": runtime.Version(),
"goroutine": runtime.NumGoroutine(),
"appVersion": "v" + base.APP_VER,
"hostname": hi.Hostname,
"platform": fmt.Sprintf("%v %v %v", hi.Platform, hi.PlatformFamily, hi.PlatformVersion),

View File

@ -59,8 +59,14 @@ func SendMail(subject, to, htmlBody string) error {
server.Port = dataSmtp.Port
server.Username = dataSmtp.Username
server.Password = dataSmtp.Password
if dataSmtp.UseSSl {
server.Encryption = mail.EncryptionSSL
switch dataSmtp.Encryption {
case "SSLTLS":
server.Encryption = mail.EncryptionSSLTLS
case "STARTTLS":
server.Encryption = mail.EncryptionSTARTTLS
default:
server.Encryption = mail.EncryptionNone
}
// Since v2.3.0 you can specified authentication type:

View File

@ -2,6 +2,7 @@
package admin
import (
"embed"
"net/http"
"net/http/pprof"
@ -9,7 +10,9 @@ import (
"github.com/gorilla/mux"
)
// 开启服务
var UiData embed.FS
// StartAdmin 开启服务
func StartAdmin() {
r := mux.NewRouter()
@ -17,7 +20,8 @@ func StartAdmin() {
r.Handle("/", http.RedirectHandler("/ui/", http.StatusFound)).Name("index")
r.PathPrefix("/ui/").Handler(
http.StripPrefix("/ui/", http.FileServer(http.Dir(base.Cfg.UiPath))),
// http.StripPrefix("/ui/", http.FileServer(http.Dir(base.Cfg.UiPath))),
http.FileServer(http.FS(UiData)),
).Name("static")
r.HandleFunc("/base/login", Login).Name("login")

View File

@ -3,5 +3,5 @@ package base
const (
APP_NAME = "AnyLink"
// 修复严重bug
APP_VER = "0.3.3"
APP_VER = "0.4.2"
)

View File

@ -39,7 +39,6 @@ type ServerConfig struct {
DbFile string `json:"db_file"`
CertFile string `json:"cert_file"`
CertKey string `json:"cert_key"`
UiPath string `json:"ui_path"`
FilesPath string `json:"files_path"`
LogPath string `json:"log_path"`
LogLevel string `json:"log_level"`
@ -70,20 +69,20 @@ type ServerConfig struct {
func initServerCfg() {
sf, _ := filepath.Abs(cfgFile)
base := filepath.Dir(sf)
// TODO 取消绝对地址转换
// sf, _ := filepath.Abs(cfgFile)
// base := filepath.Dir(sf)
// 转换成绝对路径
Cfg.DbFile = getAbsPath(base, Cfg.DbFile)
Cfg.CertFile = getAbsPath(base, Cfg.CertFile)
Cfg.CertKey = getAbsPath(base, Cfg.CertKey)
Cfg.UiPath = getAbsPath(base, Cfg.UiPath)
Cfg.FilesPath = getAbsPath(base, Cfg.FilesPath)
Cfg.LogPath = getAbsPath(base, Cfg.LogPath)
// Cfg.DbFile = getAbsPath(base, Cfg.DbFile)
// Cfg.CertFile = getAbsPath(base, Cfg.CertFile)
// Cfg.CertKey = getAbsPath(base, Cfg.CertKey)
// Cfg.UiPath = getAbsPath(base, Cfg.UiPath)
// Cfg.FilesPath = getAbsPath(base, Cfg.FilesPath)
// Cfg.LogPath = getAbsPath(base, Cfg.LogPath)
if len(Cfg.JwtSecret) < 20 {
fmt.Println("请设置 jwt_secret 长度20位以上")
os.Exit(0)
if Cfg.JwtSecret == defaultJwt {
fmt.Fprintln(os.Stderr, "=== 使用默认的jwt_secret有安全风险请设置新的jwt_secret ===")
}
fmt.Printf("ServerCfg: %+v \n", Cfg)

View File

@ -2,11 +2,9 @@ package base
import (
"fmt"
"math/rand"
"os"
"runtime"
"strings"
"time"
"github.com/bjdgyc/anylink/pkg/utils"
"github.com/spf13/cobra"
@ -63,6 +61,11 @@ func init() {
viper.SetConfigFile(cfgFile)
viper.AutomaticEnv()
if cfgFile == "" {
// 没有配置文件,不做处理
return
}
err := viper.ReadInConfig()
if err != nil {
fmt.Println("Using config file:", err)
@ -72,7 +75,7 @@ func init() {
viper.SetEnvPrefix("link")
// 基础配置
rootCmd.Flags().StringVarP(&cfgFile, "conf", "c", "./conf/server.toml", "config file")
rootCmd.Flags().StringVarP(&cfgFile, "conf", "c", "", "config file")
for _, v := range configs {
if v.Typ == cfgStr {
@ -111,7 +114,6 @@ func initToolCmd() *cobra.Command {
fmt.Printf("%s v%s build on %s [%s, %s] commit_id(%s) \n",
APP_NAME, APP_VER, runtime.Version(), runtime.GOOS, runtime.GOARCH, CommitId)
case secret:
rand.Seed(time.Now().UnixNano())
s, _ := utils.RandSecret(40, 60)
s = strings.Trim(s, "=")
fmt.Printf("Secret:%s\n", s)

View File

@ -4,6 +4,8 @@ const (
cfgStr = iota
cfgInt
cfgBool
defaultJwt = "abcdef.0123456789.abcdef"
)
type config struct {
@ -21,18 +23,17 @@ var configs = []config{
{Typ: cfgStr, Name: "server_dtls_addr", Usage: "DTLS监听地址", ValStr: ":4433"},
{Typ: cfgStr, Name: "admin_addr", Usage: "后台服务监听地址", ValStr: ":8800"},
{Typ: cfgBool, Name: "proxy_protocol", Usage: "TCP代理协议", ValBool: false},
{Typ: cfgStr, Name: "db_file", Usage: "数据库地址", ValStr: "./data.db"},
{Typ: cfgStr, Name: "cert_file", Usage: "证书文件", ValStr: "./vpn_cert.pem"},
{Typ: cfgStr, Name: "cert_key", Usage: "证书密钥", ValStr: "./vpn_cert.key"},
{Typ: cfgStr, Name: "ui_path", Usage: "ui文件路径", ValStr: "./ui"},
{Typ: cfgStr, Name: "files_path", Usage: "外部下载文件路径", ValStr: "./files"},
{Typ: cfgStr, Name: "log_path", Usage: "日志文件路径", ValStr: ""},
{Typ: cfgStr, Name: "log_level", Usage: "日志等级", ValStr: "info"},
{Typ: cfgStr, Name: "db_file", Usage: "数据库地址", ValStr: "./conf/data.db"},
{Typ: cfgStr, Name: "cert_file", Usage: "证书文件", ValStr: "./conf/vpn_cert.pem"},
{Typ: cfgStr, Name: "cert_key", Usage: "证书密钥", ValStr: "./conf/vpn_cert.key"},
{Typ: cfgStr, Name: "files_path", Usage: "外部下载文件路径", ValStr: "./conf/files"},
{Typ: cfgStr, Name: "log_path", Usage: "日志文件路径,默认标准输出", ValStr: ""},
{Typ: cfgStr, Name: "log_level", Usage: "日志等级 debug、info、warn、error", ValStr: "info"},
{Typ: cfgBool, Name: "pprof", Usage: "开启pprof", ValBool: false},
{Typ: cfgStr, Name: "issuer", Usage: "系统名称", ValStr: "XX公司VPN"},
{Typ: cfgStr, Name: "admin_user", Usage: "管理用户名", ValStr: "admin"},
{Typ: cfgStr, Name: "admin_pass", Usage: "管理用户密码", ValStr: "$2a$10$UQ7C.EoPifDeJh6d8.31TeSPQU7hM/NOM2nixmBucJpAuXDQNqNke"},
{Typ: cfgStr, Name: "jwt_secret", Usage: "JWT密钥", ValStr: "iLmspvOiz*%ovfcs*wersdf#heR8pNU4XxBm&mW$aPCjSRMbYH#&"},
{Typ: cfgStr, Name: "jwt_secret", Usage: "JWT密钥", ValStr: defaultJwt},
{Typ: cfgStr, Name: "link_mode", Usage: "虚拟网络类型", ValStr: "tun"},
{Typ: cfgStr, Name: "ipv4_cidr", Usage: "ip地址网段", ValStr: "192.168.10.0/24"},
{Typ: cfgStr, Name: "ipv4_gateway", Usage: "ipv4_gateway", ValStr: "192.168.10.1"},

View File

@ -6,10 +6,9 @@
#数据文件
db_file = "./data.db"
#证书文件
cert_file = "./test_vpn_cert.pem"
cert_key = "./test_vpn_key.pem"
ui_path = "../ui"
files_path = "../files"
cert_file = "./vpn_cert.pem"
cert_key = "./vpn_cert.key"
files_path = "./files"
#日志目录,为空写入标准输出
#log_path = "../log"
log_path = ""
@ -22,7 +21,7 @@ issuer = "XX公司VPN"
admin_user = "admin"
#pass 123456
admin_pass = "$2a$10$UQ7C.EoPifDeJh6d8.31TeSPQU7hM/NOM2nixmBucJpAuXDQNqNke"
jwt_secret = "iLmspvOiz*%ovfcs*wersdf#heR8pNU4XxBm&mW$aPCjSRMbYH#&"
jwt_secret = "abcdef.0123456789.abcdef"
#服务监听地址

View File

@ -1,19 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDGDCCAgACCQCecQDpy/8hRTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJD
TjELMAkGA1UECAwCQkoxCzAJBgNVBAcMAkJKMQswCQYDVQQKDAJCRDELMAkGA1UE
CwwCQkQxCzAJBgNVBAMMAkNTMB4XDTIxMDMyNjA5MTkwNloXDTMxMDMyNDA5MTkw
NlowTjELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAlNIMQswCQYDVQQHDAJTSDELMAkG
A1UECgwCVE0xCzAJBgNVBAsMAlRNMQswCQYDVQQDDAJDUzCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAJtDxHduS8gjI0P6txHS+cODxKjyjNiCBa7tFgSc
d9hRrzCvK4Q4M5StKJoSczmHl0C3HVoq92Gv1vENxq4irYdCrwLeOZGyt7urUlbs
PkvEoVXxfAkPpue+JewG/CvGArJeP7UGsP5IrD0Dt5X1DP677K6qf5igzyaJqYJu
RDJ5wR84BoDvY66Zc578N9tK9XusdJ63gQ5jGcG4Dneu1UX3g8lQkJ6P0xLXTh7W
u5Sjx8axbDcFxbDLxNGL1yPgAjhIRgMfaWLwuQQg4WKFsdMljv1Flz8/h91z2xo+
+E/B4YF0UFWTcWQ2TQ8w8noDqnnXVVQyOvuI3aajodml/f0CAwEAATANBgkqhkiG
9w0BAQsFAAOCAQEAd89n0eWXgO1lqMciWmS9xY8Sj/U840bPo/4Kclsm1vFNvIXu
I50PeaNiU2E5+CMk8AwXaJ5gDO7vsRxvLLRAUWZeuxSror2a0RkViEFW+UKcBuuB
Izl9giXUhB/P85+We1ma5jizqj7OpzgMkzkcTZL2M6Gw6IWY4jopvLQjiCooSiYF
wtLZjuFKfpLrPw5RgpWI4L8Hftbkmh6Q8nqcoQvgwm7rLrD5VqiTu7Rk1SXTFuXn
uuazXasWIWRVGFuFcYP1rwyOfp9HhCFKngi0w8IRnbOcaPdXydtbKMcKt5z9zQX5
BqrZ3ZfPp5HeklG7L8eQrnp4ines6YDshPnaRQ==
-----END CERTIFICATE-----

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAm0PEd25LyCMjQ/q3EdL5w4PEqPKM2IIFru0WBJx32FGvMK8r
hDgzlK0omhJzOYeXQLcdWir3Ya/W8Q3GriKth0KvAt45kbK3u6tSVuw+S8ShVfF8
CQ+m574l7Ab8K8YCsl4/tQaw/kisPQO3lfUM/rvsrqp/mKDPJompgm5EMnnBHzgG
gO9jrplznvw320r1e6x0nreBDmMZwbgOd67VRfeDyVCQno/TEtdOHta7lKPHxrFs
NwXFsMvE0YvXI+ACOEhGAx9pYvC5BCDhYoWx0yWO/UWXPz+H3XPbGj74T8HhgXRQ
VZNxZDZNDzDyegOqeddVVDI6+4jdpqOh2aX9/QIDAQABAoIBADWT2fz4g5AJiAbS
QlAVRHjSRI+kOzQPEhT93SY0NCribRjYqaSTnEEGy8b27OoCPxBm3+sYfosoGXzP
Kys17jmJqkjMFIORb1OEWAKEvS56KM42aX3a99ZqSD29X1Ffn9ibK1K1f2gP/deE
K9rEV/qjMJZJYYRyoWkEAglvMXtU/NMRoTuFYtrJPr9sFEfpBFq97WpWiyMdLKTG
MmlN+T1CXFQj/+mpv+DDSXcwLPBxAttDYE2GeqlhntId0I6cgaEGMO42D6fnqrKi
PDilA/D6zos4o/bpRGvVBdXHqOXvX2stNHK+PvEX46GRd+OZhLh0KEcrWAx8cXs9
ZhugTyECgYEAyffRPd98acL0OhXJR9mZTgDdotl7iYq+RTZbmEvAFst3mL3LA6Ba
BTrwRLh9x8lzxoTQHHFaJL63kIrN6QAR9e3+pR0e8IX3vYCVGIlRCYB5CrE/O3Pi
B9R17tCI5dFrFXYiST38sjwrWG9+geKarbUH5AZrZEO5uw0q7+4F3TkCgYEAxM1h
Xo+xRt8RXoWZ6Cl66HhZKIvDcxkBtoNh54YLzrVpv0D+RvAWNDzRVXbbIUUpBGPN
pHrwU8G0qWr4Q/Zx+vnckqotGMTNCB7vcmB/qwF9grNW9E0rCyIYLXtJcEiclJIF
Oe406YXl7mSG1I6QjAADz8PNb4++Ct1+hVS56uUCgYAx9g/Y0nQgZY2s4L7N+1Il
LammI06gE6ZF0NCPuA1oliSbsDeMShp6uL2/AjR7O6ZcMXaZ0qCN/m/CXdPaE55d
y+X2SmHg9gL26dv4Gd/mDdXjgz01I9GCRlh2Hzf+QfPPd027+I2OObwvQEV3M+s3
lVTCX6QpRWeokfVRLPxeYQKBgDIYPVK+rNdnbJps05JfDKQkDj3d5bBkiyUUKFWw
r0y8rOA8AP25m01MtdRVXs4HNruhU/UsPgRz6DK/wdY64ySJeXXzz2rgnXgVt8mb
eqPiyzn7wISLKAu7cAATw8vLD+BZku7+DYXryW13NULhzzVzw4SdSKu/IRbO7qet
u21pAoGAd2mBJ+PWKnUkARS8gQ3Y3cagA/qGGr094P9relglRDBv/Pm7kTUt6K8B
NnpqWydcVtcrXmNzGRx4ftm18SzmTJEohF14nF9424q4aiWoNZyG8adxaI0Yqv3G
LnH8n2fzC+pf31LijBRM8DRnepah64mLF+OM/SxgVg1nP9jVUG4=
-----END RSA PRIVATE KEY-----

View File

@ -33,12 +33,12 @@ func SettingGet(data interface{}) error {
}
type SettingSmtp struct {
Host string `json:"host"`
Port int `json:"port"`
Username string `json:"username"`
Password string `json:"password"`
From string `json:"from"`
UseSSl bool `json:"use_ssl"`
Host string `json:"host"`
Port int `json:"port"`
Username string `json:"username"`
Password string `json:"password"`
From string `json:"from"`
Encryption string `json:"encryption"`
}
type SettingOther struct {

View File

@ -173,6 +173,48 @@ var auth_complete = `<?xml version="1.0" encoding="UTF-8"?>
<server-cert-hash>240B97A685B2BFA66AD699B90AAC49EA66495D69</server-cert-hash>
</vpn-base-config>
<opaque is-for="vpn-client"></opaque>
<vpn-profile-manifest>
<vpn rev="1.0">
<file type="profile" service-type="user">
<uri>/profile.xml</uri>
<hash type="sha1">A8B0B07FBA93D06E8501E40AB807AEE2464E73B7</hash>
</file>
</vpn>
</vpn-profile-manifest>
</config>
</config-auth>
`
var auth_profile = `<?xml version="1.0" encoding="UTF-8"?>
<AnyConnectProfile xmlns="http://schemas.xmlsoap.org/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.xmlsoap.org/encoding/ AnyConnectProfile.xsd">
<ClientInitialization>
<UseStartBeforeLogon UserControllable="false">false</UseStartBeforeLogon>
<StrictCertificateTrust>false</StrictCertificateTrust>
<RestrictPreferenceCaching>false</RestrictPreferenceCaching>
<RestrictTunnelProtocols>IPSec</RestrictTunnelProtocols>
<BypassDownloader>true</BypassDownloader>
<WindowsVPNEstablishment>AllowRemoteUsers</WindowsVPNEstablishment>
<CertEnrollmentPin>pinAllowed</CertEnrollmentPin>
<CertificateMatch>
<KeyUsage>
<MatchKey>Digital_Signature</MatchKey>
</KeyUsage>
<ExtendedKeyUsage>
<ExtendedMatchKey>ClientAuth</ExtendedMatchKey>
</ExtendedKeyUsage>
</CertificateMatch>
<BackupServerList>
<HostAddress>localhost</HostAddress>
</BackupServerList>
</ClientInitialization>
<ServerList>
<HostEntry>
<HostName>VPN Server</HostName>
<HostAddress>localhost</HostAddress>
</HostEntry>
</ServerList>
</AnyConnectProfile>
`

View File

@ -2,27 +2,53 @@ package handler
import (
"crypto/tls"
"errors"
"fmt"
"log"
"net"
"net/http"
"os"
"time"
"github.com/pion/dtls/v2/pkg/crypto/selfsign"
"github.com/bjdgyc/anylink/base"
"github.com/bjdgyc/anylink/pkg/proxyproto"
"github.com/gorilla/mux"
)
func startTls() {
addr := base.Cfg.ServerAddr
certFile := base.Cfg.CertFile
keyFile := base.Cfg.CertKey
var (
err error
addr = base.Cfg.ServerAddr
certFile = base.Cfg.CertFile
keyFile = base.Cfg.CertKey
certs = make([]tls.Certificate, 1)
ln net.Listener
)
// 判断证书文件
_, err = os.Stat(certFile)
if errors.Is(err, os.ErrNotExist) {
// 自动生成证书
certs[0], err = selfsign.GenerateSelfSignedWithDNS("vpn.anylink")
} else {
// 使用自定义证书
certs[0], err = tls.LoadX509KeyPair(certFile, keyFile)
}
if err != nil {
panic(err)
}
// 设置tls信息
tlsConfig := &tls.Config{
NextProtos: []string{"http/1.1"},
MinVersion: tls.VersionTLS12,
InsecureSkipVerify: true,
Certificates: certs,
}
srv := &http.Server{
Addr: addr,
@ -31,9 +57,7 @@ func startTls() {
ErrorLog: base.GetBaseLog(),
}
var ln net.Listener
ln, err := net.Listen("tcp", addr)
ln, err = net.Listen("tcp", addr)
if err != nil {
log.Fatal(err)
}
@ -44,7 +68,7 @@ func startTls() {
}
base.Info("listen server", addr)
err = srv.ServeTLS(ln, certFile, keyFile)
err = srv.ServeTLS(ln, "", "")
if err != nil {
base.Fatal(err)
}
@ -56,6 +80,9 @@ func initRoute() http.Handler {
r.HandleFunc("/", LinkAuth).Methods(http.MethodPost)
r.HandleFunc("/CSCOSSLC/tunnel", LinkTunnel).Methods(http.MethodConnect)
r.HandleFunc("/otp_qr", LinkOtpQr).Methods(http.MethodGet)
r.HandleFunc("/profile.xml", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(auth_profile))
}).Methods(http.MethodGet)
r.PathPrefix("/files/").Handler(
http.StripPrefix("/files/",
http.FileServer(http.Dir(base.Cfg.FilesPath)),

View File

@ -1,21 +1,30 @@
// AnyLink 是一个企业级远程办公vpn软件可以支持多人同时在线使用。
// +build !windows
package main
import (
"embed"
"os"
"os/signal"
"syscall"
"github.com/bjdgyc/anylink/admin"
"github.com/bjdgyc/anylink/base"
"github.com/bjdgyc/anylink/handler"
)
//go:embed ui
var uiData embed.FS
// 程序版本
var COMMIT_ID string
var CommitId string
func main() {
base.CommitId = COMMIT_ID
base.CommitId = CommitId
admin.UiData = uiData
base.Start()
handler.Start()

View File

@ -58,7 +58,7 @@ func ip2long(ip net.IP) uint32 {
return binary.BigEndian.Uint32(ip)
}
// 获取动态ip
// AcquireIp 获取动态ip
func AcquireIp(username, macAddr string) net.IP {
IpPool.mux.Lock()
defer IpPool.mux.Unlock()
@ -71,37 +71,24 @@ func AcquireIp(username, macAddr string) net.IP {
if err == nil {
ip := mi.IpAddr
ipStr := ip.String()
// 跳过活跃连接
_, ok := ipActive[ipStr]
// 检测原有ip是否在新的ip池内
if IpPool.Ipv4IPNet.Contains(ip) {
if IpPool.Ipv4IPNet.Contains(ip) && !ok {
mi.Username = username
mi.LastLogin = tNow
// 回写db数据
_ = dbdata.Save(mi)
ipActive[ipStr] = true
return ip
} else {
_ = dbdata.Del(mi)
}
}
// 全局遍历未分配ip
// 优先获取没有使用的ip
for i := IpPool.IpLongMin; i <= IpPool.IpLongMax; i++ {
ip := long2ip(i)
ipStr := ip.String()
mi := &dbdata.IpMap{}
err := dbdata.One("IpAddr", ip, mi)
if err != nil && dbdata.CheckErrNotFound(err) {
// 该ip没有被使用
mi := &dbdata.IpMap{IpAddr: ip, MacAddr: macAddr, Username: username, LastLogin: tNow}
_ = dbdata.Save(mi)
ipActive[ipStr] = true
return ip
}
_ = dbdata.Del(mi)
}
farIp := &dbdata.IpMap{LastLogin: tNow}
// 遍历超过租期ip
// 全局遍历超过租期ip
for i := IpPool.IpLongMin; i <= IpPool.IpLongMax; i++ {
ip := long2ip(i)
ipStr := ip.String()
@ -112,11 +99,20 @@ func AcquireIp(username, macAddr string) net.IP {
}
v := &dbdata.IpMap{}
err := dbdata.One("IpAddr", ip, v)
err = dbdata.One("IpAddr", ip, v)
if err != nil {
if dbdata.CheckErrNotFound(err) {
// 该ip没有被使用
mi = &dbdata.IpMap{IpAddr: ip, MacAddr: macAddr, Username: username, LastLogin: tNow}
_ = dbdata.Save(mi)
ipActive[ipStr] = true
return ip
}
base.Error(err)
return nil
}
// 跳过ip保留
if v.Keep {
continue
}
@ -124,7 +120,7 @@ func AcquireIp(username, macAddr string) net.IP {
// 已经超过租期
if tNow.Sub(v.LastLogin) > time.Duration(base.Cfg.IpLease)*time.Second {
_ = dbdata.Del(v)
mi := &dbdata.IpMap{IpAddr: ip, MacAddr: macAddr, Username: username, LastLogin: tNow}
mi = &dbdata.IpMap{IpAddr: ip, MacAddr: macAddr, Username: username, LastLogin: tNow}
// 重写db数据
_ = dbdata.Save(mi)
ipActive[ipStr] = true

View File

@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"axios": "^0.20.0",
"chokidar": "^3.5.2",
"core-js": "^3.6.5",
"echarts": "^4.9.0",
"element-ui": "^2.4.5",
@ -2429,11 +2430,9 @@
"dev": true
},
"node_modules/anymatch": {
"version": "3.1.1",
"resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-3.1.1.tgz",
"integrity": "sha1-xV7PAhheJGklk5kxDBc84xIzsUI=",
"dev": true,
"optional": true,
"version": "3.1.2",
"resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-3.1.2.tgz?cache=0&sync_timestamp=1617747502795&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fanymatch%2Fdownload%2Fanymatch-3.1.2.tgz",
"integrity": "sha1-wFV8CWrzLxBhmPT04qODU343hxY=",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@ -2883,8 +2882,6 @@
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-2.1.0.tgz",
"integrity": "sha1-MPpAyef+B9vIlWeM0ocCTeokHdk=",
"dev": true,
"optional": true,
"engines": {
"node": ">=8"
}
@ -3422,10 +3419,14 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001135",
"resolved": "https://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30001135.tgz?cache=0&sync_timestamp=1600754676334&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcaniuse-lite%2Fdownload%2Fcaniuse-lite-1.0.30001135.tgz",
"integrity": "sha1-mVseuUQEo8mg12AMETybsn8s2Ko=",
"dev": true
"version": "1.0.30001240",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001240.tgz",
"integrity": "sha512-nb8mDzfMdxBDN7ZKx8chWafAdBp5DAAlpWvNyUGe5tcDWd838zpzDN3Rah9cjCqhfOKkrvx40G2SDtP0qiWX/w==",
"dev": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
}
},
"node_modules/case-sensitive-paths-webpack-plugin": {
"version": "2.3.0",
@ -3469,31 +3470,29 @@
"dev": true
},
"node_modules/chokidar": {
"version": "3.4.2",
"resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-3.4.2.tgz?cache=0&sync_timestamp=1596728935229&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-3.4.2.tgz",
"integrity": "sha1-ONyOZY3sOAl0HrPve7Ckf+QkIy0=",
"dev": true,
"optional": true,
"version": "3.5.2",
"resolved": "https://registry.nlark.com/chokidar/download/chokidar-3.5.2.tgz?cache=0&sync_timestamp=1623763452074&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchokidar%2Fdownload%2Fchokidar-3.5.2.tgz",
"integrity": "sha1-26OXb8rbAW9m/TZQIdkWANAcHnU=",
"dependencies": {
"anymatch": "~3.1.1",
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"fsevents": "~2.1.2",
"glob-parent": "~5.1.0",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.4.0"
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/chokidar/node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz",
"integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc=",
"dev": true,
"optional": true,
"dependencies": {
"fill-range": "^7.0.1"
},
@ -3505,8 +3504,6 @@
"version": "7.0.1",
"resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz",
"integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA=",
"dev": true,
"optional": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
@ -3518,8 +3515,6 @@
"version": "7.0.0",
"resolved": "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz",
"integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=",
"dev": true,
"optional": true,
"engines": {
"node": ">=0.12.0"
}
@ -3528,8 +3523,6 @@
"version": "5.0.1",
"resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-5.0.1.tgz",
"integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=",
"dev": true,
"optional": true,
"dependencies": {
"is-number": "^7.0.0"
},
@ -6375,14 +6368,10 @@
"dev": true
},
"node_modules/fsevents": {
"version": "2.1.3",
"resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-2.1.3.tgz",
"integrity": "sha1-+3OHA66NL5/pAMM4Nt3r7ouX8j4=",
"dev": true,
"version": "2.3.2",
"resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-2.3.2.tgz",
"integrity": "sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro=",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
@ -6465,10 +6454,9 @@
}
},
"node_modules/glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-5.1.1.tgz",
"integrity": "sha1-tsHvQXxOVmPqSY8cRa+saRa7wik=",
"dev": true,
"version": "5.1.2",
"resolved": "https://registry.nlark.com/glob-parent/download/glob-parent-5.1.2.tgz?cache=0&sync_timestamp=1620073438189&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglob-parent%2Fdownload%2Fglob-parent-5.1.2.tgz",
"integrity": "sha1-hpgyxYA0/mikCTwX3BXoNA2EAcQ=",
"dependencies": {
"is-glob": "^4.0.1"
},
@ -7397,8 +7385,6 @@
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-2.1.0.tgz",
"integrity": "sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=",
"dev": true,
"optional": true,
"dependencies": {
"binary-extensions": "^2.0.0"
},
@ -7537,7 +7523,6 @@
"version": "2.1.1",
"resolved": "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -7555,7 +7540,6 @@
"version": "4.0.1",
"resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz",
"integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=",
"dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
@ -8805,7 +8789,6 @@
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz",
"integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -9512,11 +9495,9 @@
"dev": true
},
"node_modules/picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npm.taobao.org/picomatch/download/picomatch-2.2.2.tgz",
"integrity": "sha1-IfMz6ba46v8CRo9RRupAbTRfTa0=",
"dev": true,
"optional": true,
"version": "2.3.0",
"resolved": "https://registry.nlark.com/picomatch/download/picomatch-2.3.0.tgz",
"integrity": "sha1-8fBh3o9qS/AiiS4tEoI0+5gwKXI=",
"engines": {
"node": ">=8.6"
}
@ -10556,11 +10537,9 @@
}
},
"node_modules/readdirp": {
"version": "3.4.0",
"resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-3.4.0.tgz",
"integrity": "sha1-n9zN+ekVWAVEkiGsZF6DA6tbmto=",
"dev": true,
"optional": true,
"version": "3.6.0",
"resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-3.6.0.tgz?cache=0&sync_timestamp=1615717369278&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-3.6.0.tgz",
"integrity": "sha1-dKNwvYVxFuJFspzJc0DNQxoCpsc=",
"dependencies": {
"picomatch": "^2.2.1"
},
@ -16342,11 +16321,9 @@
"dev": true
},
"anymatch": {
"version": "3.1.1",
"resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-3.1.1.tgz",
"integrity": "sha1-xV7PAhheJGklk5kxDBc84xIzsUI=",
"dev": true,
"optional": true,
"version": "3.1.2",
"resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-3.1.2.tgz?cache=0&sync_timestamp=1617747502795&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fanymatch%2Fdownload%2Fanymatch-3.1.2.tgz",
"integrity": "sha1-wFV8CWrzLxBhmPT04qODU343hxY=",
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@ -16733,9 +16710,7 @@
"binary-extensions": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-2.1.0.tgz",
"integrity": "sha1-MPpAyef+B9vIlWeM0ocCTeokHdk=",
"dev": true,
"optional": true
"integrity": "sha1-MPpAyef+B9vIlWeM0ocCTeokHdk="
},
"bindings": {
"version": "1.5.0",
@ -17216,9 +17191,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001135",
"resolved": "https://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30001135.tgz?cache=0&sync_timestamp=1600754676334&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcaniuse-lite%2Fdownload%2Fcaniuse-lite-1.0.30001135.tgz",
"integrity": "sha1-mVseuUQEo8mg12AMETybsn8s2Ko=",
"version": "1.0.30001240",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001240.tgz",
"integrity": "sha512-nb8mDzfMdxBDN7ZKx8chWafAdBp5DAAlpWvNyUGe5tcDWd838zpzDN3Rah9cjCqhfOKkrvx40G2SDtP0qiWX/w==",
"dev": true
},
"case-sensitive-paths-webpack-plugin": {
@ -17257,28 +17232,24 @@
"dev": true
},
"chokidar": {
"version": "3.4.2",
"resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-3.4.2.tgz?cache=0&sync_timestamp=1596728935229&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-3.4.2.tgz",
"integrity": "sha1-ONyOZY3sOAl0HrPve7Ckf+QkIy0=",
"dev": true,
"optional": true,
"version": "3.5.2",
"resolved": "https://registry.nlark.com/chokidar/download/chokidar-3.5.2.tgz?cache=0&sync_timestamp=1623763452074&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchokidar%2Fdownload%2Fchokidar-3.5.2.tgz",
"integrity": "sha1-26OXb8rbAW9m/TZQIdkWANAcHnU=",
"requires": {
"anymatch": "~3.1.1",
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"fsevents": "~2.1.2",
"glob-parent": "~5.1.0",
"fsevents": "~2.3.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.4.0"
"readdirp": "~3.6.0"
},
"dependencies": {
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz",
"integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc=",
"dev": true,
"optional": true,
"requires": {
"fill-range": "^7.0.1"
}
@ -17287,8 +17258,6 @@
"version": "7.0.1",
"resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz",
"integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA=",
"dev": true,
"optional": true,
"requires": {
"to-regex-range": "^5.0.1"
}
@ -17296,16 +17265,12 @@
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz",
"integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=",
"dev": true,
"optional": true
"integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss="
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-5.0.1.tgz",
"integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=",
"dev": true,
"optional": true,
"requires": {
"is-number": "^7.0.0"
}
@ -19688,10 +19653,9 @@
"dev": true
},
"fsevents": {
"version": "2.1.3",
"resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-2.1.3.tgz",
"integrity": "sha1-+3OHA66NL5/pAMM4Nt3r7ouX8j4=",
"dev": true,
"version": "2.3.2",
"resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-2.3.2.tgz",
"integrity": "sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro=",
"optional": true
},
"function-bind": {
@ -19757,10 +19721,9 @@
}
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-5.1.1.tgz",
"integrity": "sha1-tsHvQXxOVmPqSY8cRa+saRa7wik=",
"dev": true,
"version": "5.1.2",
"resolved": "https://registry.nlark.com/glob-parent/download/glob-parent-5.1.2.tgz?cache=0&sync_timestamp=1620073438189&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglob-parent%2Fdownload%2Fglob-parent-5.1.2.tgz",
"integrity": "sha1-hpgyxYA0/mikCTwX3BXoNA2EAcQ=",
"requires": {
"is-glob": "^4.0.1"
}
@ -20528,8 +20491,6 @@
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-2.1.0.tgz",
"integrity": "sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=",
"dev": true,
"optional": true,
"requires": {
"binary-extensions": "^2.0.0"
}
@ -20635,8 +20596,7 @@
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
},
"is-fullwidth-code-point": {
"version": "3.0.0",
@ -20648,7 +20608,6 @@
"version": "4.0.1",
"resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz",
"integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
@ -21695,8 +21654,7 @@
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz",
"integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=",
"dev": true
"integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU="
},
"normalize-range": {
"version": "0.1.2",
@ -22276,11 +22234,9 @@
"dev": true
},
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npm.taobao.org/picomatch/download/picomatch-2.2.2.tgz",
"integrity": "sha1-IfMz6ba46v8CRo9RRupAbTRfTa0=",
"dev": true,
"optional": true
"version": "2.3.0",
"resolved": "https://registry.nlark.com/picomatch/download/picomatch-2.3.0.tgz",
"integrity": "sha1-8fBh3o9qS/AiiS4tEoI0+5gwKXI="
},
"pify": {
"version": "4.0.1",
@ -23181,11 +23137,9 @@
}
},
"readdirp": {
"version": "3.4.0",
"resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-3.4.0.tgz",
"integrity": "sha1-n9zN+ekVWAVEkiGsZF6DA6tbmto=",
"dev": true,
"optional": true,
"version": "3.6.0",
"resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-3.6.0.tgz?cache=0&sync_timestamp=1615717369278&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-3.6.0.tgz",
"integrity": "sha1-dKNwvYVxFuJFspzJc0DNQxoCpsc=",
"requires": {
"picomatch": "^2.2.1"
}

View File

@ -9,6 +9,7 @@
},
"dependencies": {
"axios": "^0.20.0",
"chokidar": "^3.5.2",
"core-js": "^3.6.5",
"echarts": "^4.9.0",
"element-ui": "^2.4.5",

View File

@ -15,8 +15,12 @@
<el-form-item label="密码" prop="password">
<el-input v-model="dataSmtp.password"></el-input>
</el-form-item>
<el-form-item label="启用SSL" prop="use_ssl">
<el-switch v-model="dataSmtp.use_ssl"></el-switch>
<el-form-item label="加密类型" prop="encryption">
<el-radio-group v-model="dataSmtp.encryption">
<el-radio label="None">None</el-radio>
<el-radio label="SSLTLS">SSLTLS</el-radio>
<el-radio label="STARTTLS">STARTTLS</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="邮件from" prop="from">
<el-input v-model="dataSmtp.from"></el-input>

View File

@ -46,8 +46,9 @@
<el-card v-if="system.sys" style="margin-top: 10px">
<div slot="header">
<span>go运行环境</span>
<span>运行环境</span>
</div>
<Cell left="软件版本" :right="system.sys.appVersion" divider/>
<Cell left="GO版本" :right="system.sys.goOs" divider/>
<Cell left="GoArch" :right="system.sys.goArch" divider/>
<Cell left="GoVersion" :right="system.sys.goVersion" divider/>