feat(docker/liserAllUsers): 增加docker部署方式,新增显示所有用户列表
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,4 +2,5 @@ statik
|
||||
openvpn-manager
|
||||
.idea
|
||||
.DS_Store
|
||||
.vscode
|
||||
.vscode
|
||||
target
|
||||
17
README.md
17
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部署方式及二进制包下载集成
|
||||
- [x] 增加Docker部署方式
|
||||
- [x] 增加显示所有用户功能
|
||||
26
docker/Dockerfile
Normal file
26
docker/Dockerfile
Normal 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
11
docker/Makefile
Normal 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
55
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
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user