diff --git a/.gitignore b/.gitignore index 1771638..79f96da 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ statik openvpn-manager .idea .DS_Store -.vscode \ No newline at end of file +.vscode +target \ No newline at end of file diff --git a/README.md b/README.md index 330ae58..449d03d 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,19 @@ go get github.com/rakyll/statik go install github.com/rakyll/statik statik -src=$PWD/public CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o openvpn-manager main.go -nohup ./openvpn-manager -host openvpn服务端主机IP地址 -port openvpn管理端口 -admin-passwd OpenVPN Manager管理员admin的密码 >> /var/log/openvpn-manager.log 2>&1 & +nohup ./openvpn-manager -host openvpn服务端主机IP地址 -port openvpn管理端口 -admin-passwd OpenVPN Manager管理员admin的密码 -psw-file /etc/openvpn/server/psw-file >> /var/log/openvpn-manager.log 2>&1 & +``` + +## 3、docker方式部署 + +```bash +docker pull curiouser/openvpn-manager:v1 +docker run \ +-v $PWD/psw-file:/etc/openvpn/server/psw-file:ro \ +-p 30080:9090 \ +-it \ +curiouser/openvpn-manager:v1 \ +-host 172.16.1.2 -port 32099 -admin-passwd 12356789 -psw-file /etc/openvpn/server/psw-file ``` # 四、TODO @@ -46,4 +58,5 @@ nohup ./openvpn-manager -host openvpn服务端主机IP地址 -port openvpn管理 - [ ] 增加显示最近五条登录日志 - [ ] 增加新增用户的功能 - [ ] 增加对低版本OpenVPN的支持 -- [ ] 增加Docker部署方式及二进制包下载集成 \ No newline at end of file +- [x] 增加Docker部署方式 +- [x] 增加显示所有用户功能 \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..3c0a3a6 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,26 @@ +FROM alpine:3.11.5 + +ENV LANG=en_US.UTF-8 \ + LANGUAGE=en_US.UTF-8 \ + TZ=Asia/Shanghai + + +RUN sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories \ + && apk add --no-cache dumb-init ca-certificates tzdata bash bash-doc bash-completion \ + && wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub \ + && wget -q https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.29-r0/glibc-2.29-r0.apk \ + && wget -q https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.29-r0/glibc-bin-2.29-r0.apk \ + && wget -q https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.29-r0/glibc-i18n-2.29-r0.apk \ + && apk add glibc-2.29-r0.apk glibc-bin-2.29-r0.apk glibc-i18n-2.29-r0.apk \ + && rm -rf /opt/jdk-8u241-linux-x64.tar.gz /usr/lib/jvm glibc-2.29-r0.apk glibc-bin-2.29-r0.apk glibc-i18n-2.29-r0.apk \ + && /usr/glibc-compat/bin/localedef --force --inputfile POSIX --charmap UTF-8 "$LANG" || true \ + && echo "export LANG=$LANG" > /etc/profile.d/locale.sh \ + && apk del glibc-i18n \ + && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ + && echo "Asia/Shanghai" > /etc/timezone + +ENTRYPOINT ["dumb-init", "--","/applications/openvpn-manager"] + +COPY target /applications + +WORKDIR /applications diff --git a/docker/Makefile b/docker/Makefile new file mode 100644 index 0000000..3aceadc --- /dev/null +++ b/docker/Makefile @@ -0,0 +1,11 @@ +REGISTRY = docker.io +IMAGE_REPO = curiouser +IMAGE_NAME = openvpn-manager +IMAGE_VERSION = v1 +all: build push +build: + rm -rf statik target && statik -src=public + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o target/openvpn-manager main.go + docker build --rm -f docker/Dockerfile -t ${REGISTRY}/${IMAGE_REPO}/${IMAGE_NAME}:${IMAGE_VERSION} . +push: + docker push ${REGISTRY}/${IMAGE_REPO}/${IMAGE_NAME}:${IMAGE_VERSION} \ No newline at end of file diff --git a/main.go b/main.go index 16d1732..cfd800e 100644 --- a/main.go +++ b/main.go @@ -1,13 +1,15 @@ -//go:generate statik -src=./public +//go:generate statik -src=$PWD/public package main import ( _ "curiouser.com/openvpn-manager/statik" + "encoding/csv" "encoding/json" "flag" "fmt" "github.com/gin-gonic/gin" "github.com/rakyll/statik/fs" + "io/ioutil" "log" "net" "net/http" @@ -32,13 +34,22 @@ type OnlineClients struct { Onlineclients []ClientConInfo `json:"onlineclient"` } +type User struct { + Username string `json:"username"` +} + +type Users struct { + Users []User `json:"users"` +} + var ( - ip_reg = regexp.MustCompile(`(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}`) - port_reg = regexp.MustCompile(`\((.*?)\)`) - omhost string - omport string - ompasswd string + ip_reg = regexp.MustCompile(`(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}`) + port_reg = regexp.MustCompile(`\((.*?)\)`) + omhost string + omport string + ompasswd string omadminpassw string + omvpnpswfile string router *gin.Engine authorizedRoute *gin.RouterGroup @@ -49,7 +60,8 @@ func init() { flag.StringVar(&omhost, "host", "", "OpenVPN服务端地址") flag.StringVar(&omport, "port", "", "OpenVPN服务端管理端口,默认为空") flag.StringVar(&ompasswd, "passwd", "", "OpenVPN服务端管理端口密码") - flag.StringVar(&omadminpassw,"admin-passwd","","OpenVPN Manager管理员admin的密码") + flag.StringVar(&omadminpassw, "admin-passwd", "", "OpenVPN Manager管理员admin的密码") + flag.StringVar(&omvpnpswfile, "psw-file", "", "OpenVPN用于验证用户的密码文件") flag.Parse() gin.SetMode(gin.ReleaseMode) @@ -64,8 +76,8 @@ func init() { func main() { - if omhost == "" && omport == "" && omadminpassw == ""{ - fmt.Println("没有设置OpenVPN服务端的主机IP地址、管理端口及管理员密码,请在启动命令后添加'-host','-port','-admin-passwd'参数设置") + if omhost == "" && omport == "" && omadminpassw == "" && omvpnpswfile == "" { + fmt.Println("没有设置OpenVPN服务端的主机IP地址、管理端口及管理员密码,请在启动命令后添加'-host','-port','-admin-passwd','-omvpnpswfile'参数设置") os.Exit(0) } else if omhost == "" { fmt.Println("OpenVPN服务端主机IP地址没有设置,无法启动。请在启动命令后添加'-host'参数设置IP地址") @@ -73,9 +85,12 @@ func main() { } else if omport == "" { fmt.Println("OpenVPN管理端口没有设置,无法启动。请在启动命令后添加'-port'参数设置管理端口号") os.Exit(0) - }else if omadminpassw == "" { + } else if omadminpassw == "" { fmt.Println("OpenVPN Manager管理员admin用户的密码没有设置,无法启动。请在启动命令后添加'-admin-passwd'参数进行设置") os.Exit(0) + } else if omvpnpswfile == "" { + fmt.Println("OpenVPN用于验证用户的密码文件路径没有设置,无法启动。请在启动命令后添加'-omvpnpswfile'参数进行设置") + os.Exit(0) } statikFS, err := fs.New() @@ -90,6 +105,7 @@ func main() { }) authorizedRoute.StaticFS("/public", statikFS) + //authorizedRoute.StaticFS("/public",http.Dir("./public")) authorizedRoute.StaticFile("/favicon.ico", "./public/favicon.ico") authorizedRoute.GET("/getOnlineClients", func(context *gin.Context) { @@ -125,6 +141,24 @@ func main() { username := context.PostForm("username") _ = sendDataToSocket(omhost+":"+omport, "kill "+username) }) + authorizedRoute.GET("/getAllUsers", func(context *gin.Context) { + filedata, err := ioutil.ReadFile(omvpnpswfile) + if err != nil { + fmt.Println("读取文件失败!") + } + r2 := csv.NewReader(strings.NewReader(string(filedata))) + ss, _ := r2.ReadAll() + sz := len(ss) + var euser *User + var eusers Users + // 循环取数据 + for i := 0; i < sz; i++ { + euser = &User{Username: strings.Split(ss[i][0], " ")[0]} + eusers.Users = append(eusers.Users, *euser) + } + json, _ := json.Marshal(eusers) + context.JSON(http.StatusOK, string(json)) + }) fmt.Println("OpenVPN Manager监听端口9090,访问地址:http://127.0.0.1:9090") router.Run(":9090") @@ -153,4 +187,3 @@ func sendDataToSocket(conf string, msg string) (resData []byte) { return buf1 } - diff --git a/public/index.html b/public/index.html index d9c93f7..bbcd8e0 100644 --- a/public/index.html +++ b/public/index.html @@ -8,7 +8,6 @@ +

OpenVPN在线用户列表

ID 用户名 客户端路由公网IP地址 端口 虚拟IP地址 接收数据大小 发送数据大小 连接时间 是否下线用户
+

所有用户列表

+ + + +
用户名
+