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地址 | 接收数据大小 | 发送数据大小 | 连接时间 | 是否下线用户 |
+所有用户列表
+
+