feat(docker/liserAllUsers): 增加docker部署方式,新增显示所有用户列表

This commit is contained in:
王永乐
2021-01-26 18:03:29 +08:00
parent 3cc518ea61
commit 3ca5ce2a99
6 changed files with 130 additions and 19 deletions

3
.gitignore vendored
View File

@@ -2,4 +2,5 @@ statik
openvpn-manager
.idea
.DS_Store
.vscode
.vscode
target

View File

@@ -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部署方式及二进制包下载集成
- [x] 增加Docker部署方式
- [x] 增加显示所有用户功能

26
docker/Dockerfile Normal file
View File

@@ -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

11
docker/Makefile Normal file
View File

@@ -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}

55
main.go
View File

@@ -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
}

View File

@@ -8,7 +8,6 @@
<script type="text/javascript">
let reg = /\\/g;
function getBytesSize(size) {//把字节转换成正常文件大小
if (!size) return "";
var num = 1024.00; //byte
@@ -22,7 +21,6 @@
return (size / Math.pow(num, 3)).toFixed(2) + "G"; //G
return (size / Math.pow(num, 4)).toFixed(2) + "T"; //T
}
function formatDuring(mss){
var days = parseInt(mss / ( 60 * 60 * 24));
var hours = parseInt((mss % ( 60 * 60 * 24)) / ( 60 * 60));
@@ -34,11 +32,11 @@
var ajaxObj = new XMLHttpRequest();
ajaxObj.open('get', '/getOnlineClients');
ajaxObj.send();
ajaxObj.responseType = 'json';
ajaxObj.onreadystatechange = function () {
if (ajaxObj.readyState == 4 && ajaxObj.status == 200) {
var originData = ajaxObj.responseText.replace(reg,'').substr(1)
var originJsonData = originData.substring(0,originData.length - 1)
var myObj = JSON.parse(originJsonData);
var res = this.response;
var myObj = JSON.parse(res);
var txt = "";
for (let x=0;x < myObj.onlineclient.length;x++){
var nowTs=parseInt(new Date().getTime()/1000)
@@ -67,8 +65,30 @@
ajaxObj.open('post', "/kickOutClientByCN",false,);
ajaxObj.send(formData);
};
function getAllUsers(){
var xhr = new XMLHttpRequest();
xhr.open('get', "/getAllUsers");
xhr.send();
xhr.responseType = 'json';
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var res = this.response;
var myObj = JSON.parse(res);
var usertxt = "";
for (let x=0;x < myObj.users.length;x++){
usertxt += "<tr>"
+ "<td>" + (x+1) + "</td>"
+ "<td>" + myObj.users[x].username + "</td>"
+ "</tr>";
console.log(myObj.users[x].username)
}
document.querySelector("#allusers").insertAdjacentHTML('afterBegin',usertxt)
}
}
}
window.onload=function() {
getOnlineClients();
getAllUsers();
document.getElementById("onlineClientsTable").addEventListener('click', function (e) {
if(e.target.className === 'kickOutBtn') {
kickOutClientByCN(e.target.getAttribute('client_username'));
@@ -76,11 +96,18 @@
})
}
</script>
<h1 align="center">OpenVPN在线用户列表</h1>
<table width="1300" height="100" border="2" cellpadding="15" cellspacing="0" align="center" >
<tr> <th>ID</th> <th>用户名</th> <th>客户端路由公网IP地址</th> <th>端口</th> <th>虚拟IP地址</th> <th>接收数据大小</th> <th>发送数据大小</th> <th>连接时间</th> <th>是否下线用户</th> </tr>
<tbody id="onlineClientsTable"> </tbody>
</table>
<h1 align="center">所有用户列表</h1>
<table width="100" height="100" border="2" cellpadding="15" cellspacing="0" align="center" >
<tr> <th></th> <th>用户名</th> </tr>
<tbody id="allusers"> </tbody>
</table>
</body>
</html>