Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a951b982b3 | ||
|
|
a33be66504 | ||
|
|
f41b9d5887 | ||
|
|
3c608463e6 | ||
|
|
eeffbe124a | ||
|
|
d7f2d54faa | ||
|
|
7db4b03634 | ||
|
|
77760a681a | ||
|
|
f9c1447ceb | ||
|
|
fb749c1902 |
@@ -1,4 +1,4 @@
|
||||
FROM rustdesk/rustdesk-server-s6:latest as server
|
||||
FROM rustdesk/rustdesk-server-s6:latest AS server
|
||||
|
||||
FROM alpine
|
||||
|
||||
|
||||
73
README.md
@@ -34,6 +34,7 @@
|
||||
- 快速使用web client
|
||||
- i18n
|
||||
- 通过 web client 分享给游客
|
||||
- server控制(一些官方的简单的指令 [WIKI](https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command))
|
||||
- Web Client
|
||||
- 自动获取API server
|
||||
- 自动获取ID服务器和KEY
|
||||
@@ -75,14 +76,14 @@
|
||||
2. 普通用户界面
|
||||

|
||||
右上角可以更改密码,可以切换语言,可以切换`白天/黑夜`模式
|
||||
|
||||

|
||||
|
||||
3. 分组可以自定义,方便管理,暂时支持两种类型: `共享组` 和 `普通组`
|
||||

|
||||
4. 可以直接打开webclient,方便使用;也可以分享给游客,游客可以直接通过webclient远程到设备
|
||||
|
||||
3. 每个用户可以多个地址簿,也可以将地址簿共享给其他用户
|
||||
4. 分组可以自定义,方便管理,暂时支持两种类型: `共享组` 和 `普通组`
|
||||
5. 可以直接打开webclient,方便使用;也可以分享给游客,游客可以直接通过webclient远程到设备
|
||||

|
||||
5. Oauth,支持了`Github`, `Google` 以及 `OIDC`, 需要创建一个`OAuth App`,然后配置到后台
|
||||
6. Oauth,支持了`Github`, `Google` 以及 `OIDC`, 需要创建一个`OAuth App`,然后配置到后台
|
||||

|
||||
- 对于`Google` 和 `Github`, `Issuer` 和 `Scopes`不需要填写.
|
||||
- 对于`OIDC`, `Issuer`是必须的。`Scopes`是可选的,默认为 `openid,profile,email`. 确保可以获取 `sub`,`email` 和`preferred_username`
|
||||
@@ -90,6 +91,21 @@
|
||||
中创建,地址 [https://github.com/settings/developers](https://github.com/settings/developers)
|
||||
- `Authorization callback URL`填写`http://<your server[:port]>/api/oauth/callback`
|
||||
,比如`http://127.0.0.1:21114/api/oauth/callback`
|
||||
7. 登录日志
|
||||
8. 链接日志
|
||||
9. 文件传输日志
|
||||
10. server控制
|
||||
|
||||
- `简易模式`,已经界面化了一些简单的指令,可以直接在后台执行
|
||||

|
||||
|
||||
- `高级模式`,直接在后台执行指令
|
||||
* 可以官方指令
|
||||
* 可以添加自定义指令
|
||||
* 可以执行自定义指令
|
||||
|
||||

|
||||
|
||||
|
||||
### Web Client:
|
||||
|
||||
@@ -160,6 +176,9 @@ logger:
|
||||
proxy:
|
||||
enable: false
|
||||
host: ""
|
||||
jwt:
|
||||
key: ""
|
||||
expire-duration: 360000
|
||||
```
|
||||
|
||||
### 环境变量
|
||||
@@ -198,6 +217,9 @@ proxy:
|
||||
| ----PROXY配置----- | --------------- | ---------- |
|
||||
| RUSTDESK_API_PROXY_ENABLE | 是否启用代理:`false`, `true` | `false` |
|
||||
| RUSTDESK_API_PROXY_HOST | 代理地址 | `http://127.0.0.1:1080` |
|
||||
| ----JWT配置---- | -------- | -------- |
|
||||
| RUSTDESK_API_JWT_KEY | 自定义JWT KEY,为空则不启用JWT | |
|
||||
| RUSTDESK_API_JWT_EXPIRE_DURATION | JWT有效时间 | 360000 |
|
||||
|
||||
|
||||
### 运行
|
||||
@@ -263,8 +285,49 @@ proxy:
|
||||
6. 打开浏览器访问`http://<your server[:port]>/_admin/`,默认用户名密码为`admin`,请及时更改密码。
|
||||
|
||||
|
||||
#### 使用我fork后的server-s6镜像运行
|
||||
|
||||
- github https://github.com/lejianwen/rustdesk-server
|
||||
- docker hub https://hub.docker.com/r/lejianwen/rustdesk-server-s6
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
rustdesk-net:
|
||||
external: false
|
||||
services:
|
||||
rustdesk:
|
||||
ports:
|
||||
- 21114:21114
|
||||
- 21115:21115
|
||||
- 21116:21116
|
||||
- 21116:21116/udp
|
||||
- 21117:21117
|
||||
- 21118:21118
|
||||
- 21119:21119
|
||||
image: lejianwen/rustdesk-server-s6:latest
|
||||
environment:
|
||||
- RELAY=<relay_server[:port]>
|
||||
- ENCRYPTED_ONLY=1
|
||||
- MUST_LOGIN=N
|
||||
- TZ=Asia/Shanghai
|
||||
- RUSTDESK_API_RUSTDESK_ID_SERVER=<id_server[:21116]>
|
||||
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=<relay_server[:21117]>
|
||||
- RUSTDESK_API_RUSTDESK_API_SERVER=http://<api_server[:21114]>
|
||||
- RUSTDESK_API_KEY_FILE=/data/id_ed25519.pub
|
||||
- RUSTDESK_API_JWT_KEY=xxxxxx # jwt key
|
||||
volumes:
|
||||
- /data/rustdesk/server:/data
|
||||
- /data/rustdesk/api:/app/data #将数据库挂载
|
||||
networks:
|
||||
- rustdesk-net
|
||||
restart: unless-stopped
|
||||
|
||||
```
|
||||
|
||||
|
||||
## 其他
|
||||
|
||||
- [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
||||
- [链接超时问题](https://github.com/lejianwen/rustdesk-api/issues/92)
|
||||
- [修改客户端ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
|
||||
- [webclient来源](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
|
||||
137
README_EN.md
@@ -33,6 +33,7 @@ desktop software that provides self-hosted solutions.
|
||||
- Quick access to web client
|
||||
- i18n
|
||||
- Share to guest by web client
|
||||
- Server control (some simple official commands [WIKI](https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command))
|
||||
- Web Client
|
||||
- Automatically obtain API server
|
||||
- Automatically obtain ID server and KEY
|
||||
@@ -78,12 +79,11 @@ installation are `admin` `admin`, please change the password immediately.
|
||||
In the top right corner, you can change the password, switch languages, and toggle between `day/night` mode.
|
||||
|
||||

|
||||
3. Groups can be customized for easy management. Currently, two types are supported: `shared group` and `regular group`.
|
||||

|
||||
4. You can directly launch the client or open the web client for convenience; you can also share it with guests, who can remotely access the device via the web client.
|
||||
|
||||
3. Each user can have multiple address books, which can also be shared with other users.
|
||||
4. Groups can be customized for easy management. Currently, two types are supported: `shared group` and `regular group`.
|
||||
5. You can directly launch the client or open the web client for convenience; you can also share it with guests, who can remotely access the device via the web client.
|
||||

|
||||
5. OAuth support: Currently, `GitHub`, `Google` and `OIDC` are supported. You need to create an `OAuth App` and configure it in
|
||||
6. OAuth support: Currently, `GitHub`, `Google` and `OIDC` are supported. You need to create an `OAuth App` and configure it in
|
||||
the admin panel.
|
||||

|
||||
- For `Google` and `Github`, you don't need to fill the `Issuer` and `Scpoes`
|
||||
@@ -92,6 +92,23 @@ installation are `admin` `admin`, please change the password immediately.
|
||||
at `Settings` -> `Developer settings` -> `OAuth Apps` -> `New OAuth App` [here](https://github.com/settings/developers).
|
||||
- Set the `Authorization callback URL` to `http://<your server[:port]>/api/oauth/callback`,
|
||||
e.g., `http://127.0.0.1:21114/api/oauth/callback`.
|
||||
|
||||
7. Login logs
|
||||
8. Connection logs
|
||||
9. File transfer logs
|
||||
10. Server control
|
||||
|
||||
- `Simple mode`, some simple commands have been GUI-ized and can be executed directly in the backend
|
||||

|
||||
|
||||
- `Advanced mode`, commands can be executed directly in the backend
|
||||
* Official commands can be used
|
||||
* Custom commands can be added
|
||||
* Custom commands can be executed
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### Web Client:
|
||||
|
||||
@@ -162,44 +179,50 @@ logger:
|
||||
proxy:
|
||||
enable: false
|
||||
host: ""
|
||||
jwt:
|
||||
key: ""
|
||||
expire-duration: 360000
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
The prefix for variable names is `RUSTDESK_API`. If environment variables exist, they will override the configurations in the configuration file.
|
||||
|
||||
| Variable Name | Description | Example |
|
||||
|-----------------------------------------------------|--------------------------------------------------------------------------------------------------------------|-------------------------------|
|
||||
| TZ | timezone | Asia/Shanghai |
|
||||
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
|
||||
| RUSTDESK_API_APP_WEB_CLIENT | web client on/off; 1: on, 0 off, default: 1 | 1 |
|
||||
| RUSTDESK_API_APP_REGISTER | register enable; `true`, `false`; default:`false` | `false` |
|
||||
| RUSTDESK_API_APP_SHOW_SWAGGER | swagger visible; 1: yes, 0: no; default: 0 | `0` |
|
||||
| ----- ADMIN Configuration----- | ---------- | ---------- |
|
||||
| RUSTDESK_API_ADMIN_TITLE | Admin Title | `RustDesk Api Admin` |
|
||||
| RUSTDESK_API_ADMIN_HELLO | Admin welcome message, you can use `html` | |
|
||||
| RUSTDESK_API_ADMIN_HELLO_FILE | Admin welcome message file,<br>will override `RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
|
||||
| ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
|
||||
| ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||
| RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite |
|
||||
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 |
|
||||
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
|
||||
| RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
|
||||
| ----- MYSQL Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
|
||||
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
|
||||
| RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 |
|
||||
| RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk |
|
||||
| ----- RUSTDESK Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk ID server address | 192.168.1.66:21116 |
|
||||
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk relay server address | 192.168.1.66:21117 |
|
||||
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk API server address | http://192.168.1.66:21114 |
|
||||
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk key | 123456789 |
|
||||
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk key file | `./conf/data/id_ed25519.pub` |
|
||||
| RUSTDESK_API_RUSTDESK_WEBCLIENT_MAGIC_QUERYONLINE | New online query method is enabled in the web client v2; '1': Enabled, '0': Disabled, not enabled by default | `0` |
|
||||
| ---- PROXY ----- | --------------- | ---------- |
|
||||
| RUSTDESK_API_PROXY_ENABLE | proxy_enable :`false`, `true` | `false` |
|
||||
| RUSTDESK_API_PROXY_HOST | proxy_host | `http://127.0.0.1:1080` |
|
||||
| Variable Name | Description | Example |
|
||||
|---------------------------------------------------|--------------------------------------------------------------------------------------------------------------|-------------------------------|
|
||||
| TZ | timezone | Asia/Shanghai |
|
||||
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
|
||||
| RUSTDESK_API_APP_WEB_CLIENT | web client on/off; 1: on, 0 off, default: 1 | 1 |
|
||||
| RUSTDESK_API_APP_REGISTER | register enable; `true`, `false`; default:`false` | `false` |
|
||||
| RUSTDESK_API_APP_SHOW_SWAGGER | swagger visible; 1: yes, 0: no; default: 0 | `0` |
|
||||
| ----- ADMIN Configuration----- | ---------- | ---------- |
|
||||
| RUSTDESK_API_ADMIN_TITLE | Admin Title | `RustDesk Api Admin` |
|
||||
| RUSTDESK_API_ADMIN_HELLO | Admin welcome message, you can use `html` | |
|
||||
| RUSTDESK_API_ADMIN_HELLO_FILE | Admin welcome message file,<br>will override `RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
|
||||
| ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
|
||||
| ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||
| RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite |
|
||||
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 |
|
||||
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
|
||||
| RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
|
||||
| ----- MYSQL Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
|
||||
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
|
||||
| RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 |
|
||||
| RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk |
|
||||
| ----- RUSTDESK Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk ID server address | 192.168.1.66:21116 |
|
||||
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk relay server address | 192.168.1.66:21117 |
|
||||
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk API server address | http://192.168.1.66:21114 |
|
||||
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk key | 123456789 |
|
||||
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk key file | `./conf/data/id_ed25519.pub` |
|
||||
| RUSTDESK_API_RUSTDESK_WEBCLIENT_MAGIC_QUERYONLINE | New online query method is enabled in the web client v2; '1': Enabled, '0': Disabled, not enabled by default | `0` |
|
||||
| ---- PROXY ----- | --------------- | ---------- |
|
||||
| RUSTDESK_API_PROXY_ENABLE | proxy_enable :`false`, `true` | `false` |
|
||||
| RUSTDESK_API_PROXY_HOST | proxy_host | `http://127.0.0.1:1080` |
|
||||
| ----JWT---- | -------- | -------- |
|
||||
| RUSTDESK_API_JWT_KEY | JWT KEY. Set empty to disable jwt | |
|
||||
| RUSTDESK_API_JWT_EXPIRE_DURATION | JWT expire duration | 360000 |
|
||||
|
||||
### Installation Steps
|
||||
|
||||
@@ -268,9 +291,47 @@ Download the release from [release](https://github.com/lejianwen/rustdesk-api/re
|
||||
6. Open your browser and visit `http://<your server[:port]>/_admin/`, with default credentials `admin admin`. Please
|
||||
change the password promptly.
|
||||
|
||||
#### Running with my forked server-s6 image
|
||||
|
||||
- github https://github.com/lejianwen/rustdesk-server
|
||||
- docker hub https://hub.docker.com/r/lejianwen/rustdesk-server-s6
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
rustdesk-net:
|
||||
external: false
|
||||
services:
|
||||
rustdesk:
|
||||
ports:
|
||||
- 21114:21114
|
||||
- 21115:21115
|
||||
- 21116:21116
|
||||
- 21116:21116/udp
|
||||
- 21117:21117
|
||||
- 21118:21118
|
||||
- 21119:21119
|
||||
image: lejianwen/rustdesk-server-s6:latest
|
||||
environment:
|
||||
- RELAY=<relay_server[:port]>
|
||||
- ENCRYPTED_ONLY=1
|
||||
- MUST_LOGIN=N
|
||||
- TZ=Asia/Shanghai
|
||||
- RUSTDESK_API_RUSTDESK_ID_SERVER=<id_server[:21116]>
|
||||
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=<relay_server[:21117]>
|
||||
- RUSTDESK_API_RUSTDESK_API_SERVER=http://<api_server[:21114]>
|
||||
- RUSTDESK_API_KEY_FILE=/data/id_ed25519.pub
|
||||
- RUSTDESK_API_JWT_KEY=xxxxxx # jwt key
|
||||
volumes:
|
||||
- /data/rustdesk/server:/data
|
||||
- /data/rustdesk/api:/app/data #将数据库挂载
|
||||
networks:
|
||||
- rustdesk-net
|
||||
restart: unless-stopped
|
||||
|
||||
```
|
||||
## Others
|
||||
|
||||
- [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
||||
- [Connection Timeout](https://github.com/lejianwen/rustdesk-api/issues/92)
|
||||
- [Change client ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
|
||||
- [Web client source](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"Gwen/global"
|
||||
"Gwen/http"
|
||||
"Gwen/lib/cache"
|
||||
"Gwen/lib/jwt"
|
||||
"Gwen/lib/lock"
|
||||
"Gwen/lib/logger"
|
||||
"Gwen/lib/orm"
|
||||
@@ -17,6 +18,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// @title 管理系统API
|
||||
@@ -163,13 +165,13 @@ func InitGlobal() {
|
||||
|
||||
//jwt
|
||||
//fmt.Println(global.Config.Jwt.PrivateKey)
|
||||
//global.Jwt = jwt.NewJwt(global.Config.Jwt.PrivateKey, global.Config.Jwt.ExpireDuration*time.Second)
|
||||
global.Jwt = jwt.NewJwt(global.Config.Jwt.Key, global.Config.Jwt.ExpireDuration*time.Second)
|
||||
|
||||
//locker
|
||||
global.Lock = lock.NewLocal()
|
||||
}
|
||||
func DatabaseAutoUpdate() {
|
||||
version := 251
|
||||
version := 260
|
||||
|
||||
db := global.DB
|
||||
|
||||
|
||||
@@ -26,16 +26,19 @@ rustdesk:
|
||||
relay-server: "192.168.1.66:21117"
|
||||
api-server: "http://127.0.0.1:21114"
|
||||
key: ""
|
||||
key-file: "./conf/data/id_ed25519.pub"
|
||||
key-file: "/data/id_ed25519.pub"
|
||||
personal: 1
|
||||
webclient-magic-queryonline: 0
|
||||
logger:
|
||||
path: "./runtime/log.txt"
|
||||
level: "warn" #trace,debug,info,warn,error,fatal
|
||||
level: "debug" #trace,debug,info,warn,error,fatal
|
||||
report-caller: true
|
||||
proxy:
|
||||
enable: false
|
||||
host: "http://127.0.0.1:1080"
|
||||
jwt:
|
||||
key: ""
|
||||
expire-duration: 360000
|
||||
redis:
|
||||
addr: "127.0.0.1:6379"
|
||||
password: ""
|
||||
@@ -53,6 +56,4 @@ oss:
|
||||
callback-url: ""
|
||||
expire-time: 30
|
||||
max-byte: 10240
|
||||
jwt:
|
||||
private-key: "./conf/jwt_pri.pem"
|
||||
expire-duration: 360000
|
||||
|
||||
|
||||
@@ -3,6 +3,6 @@ package config
|
||||
import "time"
|
||||
|
||||
type Jwt struct {
|
||||
PrivateKey string `mapstructure:"private-key"`
|
||||
Key string `mapstructure:"key"`
|
||||
ExpireDuration time.Duration `mapstructure:"expire-duration"`
|
||||
}
|
||||
|
||||
BIN
docs/en_img/rustdesk_command_advance.png
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
docs/en_img/rustdesk_command_simple.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 19 KiB |
BIN
docs/rustdesk_command_advance.png
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
docs/rustdesk_command_simple.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 48 KiB |
@@ -15,6 +15,7 @@ type Rustdesk struct {
|
||||
type RustdeskCmd struct {
|
||||
Cmd string `json:"cmd"`
|
||||
Option string `json:"option"`
|
||||
Target string `json:"target"`
|
||||
}
|
||||
|
||||
func (r *Rustdesk) CmdList(c *gin.Context) {
|
||||
@@ -26,7 +27,8 @@ func (r *Rustdesk) CmdList(c *gin.Context) {
|
||||
res := service.AllService.ServerCmdService.List(q.Page, 9999)
|
||||
//在列表前添加系统命令
|
||||
list := make([]*model.ServerCmd, 0)
|
||||
list = append(list, model.SysServerCmds...)
|
||||
list = append(list, model.SysIdServerCmds...)
|
||||
list = append(list, model.SysRelayServerCmds...)
|
||||
list = append(list, res.ServerCmds...)
|
||||
res.ServerCmds = list
|
||||
response.Success(c, res)
|
||||
@@ -101,12 +103,23 @@ func (r *Rustdesk) CmdUpdate(c *gin.Context) {
|
||||
|
||||
func (r *Rustdesk) SendCmd(c *gin.Context) {
|
||||
rc := &RustdeskCmd{}
|
||||
c.ShouldBindJSON(rc)
|
||||
if rc.Cmd == "" {
|
||||
response.Fail(c, 101, "cmd is required")
|
||||
if err := c.ShouldBindJSON(rc); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
res, err := service.AllService.ServerCmdService.SendCmd(rc.Cmd, rc.Option)
|
||||
if rc.Cmd == "" {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
if rc.Target == "" {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
if rc.Target != model.ServerCmdTargetIdServer && rc.Target != model.ServerCmdTargetRelayServer {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
res, err := service.AllService.ServerCmdService.SendCmd(rc.Target, rc.Cmd, rc.Option)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, err.Error())
|
||||
return
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"Gwen/global"
|
||||
"Gwen/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -27,7 +28,21 @@ func RustAuth() gin.HandlerFunc {
|
||||
//提取token,格式是Bearer {token}
|
||||
//这里只是简单的提取
|
||||
token = token[7:]
|
||||
|
||||
//验证token
|
||||
|
||||
//检查是否设置了jwt key
|
||||
if len(global.Jwt.Key) > 0 {
|
||||
uid, _ := service.AllService.UserService.VerifyJWT(token)
|
||||
if uid == 0 {
|
||||
c.JSON(401, gin.H{
|
||||
"error": "Unauthorized",
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
user, ut := service.AllService.UserService.InfoByAccessToken(token)
|
||||
if user.Id == 0 {
|
||||
c.JSON(401, gin.H{
|
||||
@@ -38,7 +53,7 @@ func RustAuth() gin.HandlerFunc {
|
||||
}
|
||||
if !service.AllService.UserService.CheckUserEnable(user) {
|
||||
c.JSON(401, gin.H{
|
||||
"error": "账号已被禁用",
|
||||
"error": "Unauthorized",
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Jwt struct {
|
||||
privateKey *rsa.PrivateKey
|
||||
Key []byte
|
||||
TokenExpireDuration time.Duration
|
||||
}
|
||||
|
||||
@@ -17,31 +16,28 @@ type UserClaims struct {
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
func NewJwt(privateKeyFile string, tokenExpireDuration time.Duration) *Jwt {
|
||||
privateKeyContent, err := os.ReadFile(privateKeyFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(privateKeyContent)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
func NewJwt(key string, tokenExpireDuration time.Duration) *Jwt {
|
||||
return &Jwt{
|
||||
privateKey: privateKey,
|
||||
Key: []byte(key),
|
||||
TokenExpireDuration: tokenExpireDuration,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Jwt) GenerateToken(userId uint) string {
|
||||
t := jwt.NewWithClaims(jwt.SigningMethodRS256,
|
||||
if len(s.Key) == 0 {
|
||||
fmt.Println("jwt key is nil")
|
||||
return ""
|
||||
}
|
||||
t := jwt.NewWithClaims(jwt.SigningMethodHS256,
|
||||
UserClaims{
|
||||
UserId: userId,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(s.TokenExpireDuration)),
|
||||
},
|
||||
})
|
||||
token, err := t.SignedString(s.privateKey)
|
||||
token, err := t.SignedString(s.Key)
|
||||
if err != nil {
|
||||
fmt.Printf("jwt token generate error: %v", err)
|
||||
return ""
|
||||
}
|
||||
return token
|
||||
@@ -49,7 +45,7 @@ func (s *Jwt) GenerateToken(userId uint) string {
|
||||
|
||||
func (s *Jwt) ParseToken(tokenString string) (uint, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return s.privateKey.Public(), nil
|
||||
return s.Key, nil
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
||||
@@ -6,6 +6,7 @@ type ServerCmd struct {
|
||||
Alias string `json:"alias" gorm:"default:'';not null;"`
|
||||
Option string `json:"option" gorm:"default:'';not null;"`
|
||||
Explain string `json:"explain" gorm:"default:'';not null;"`
|
||||
Target string `json:"target" gorm:"default:'';not null;"`
|
||||
TimeModel
|
||||
}
|
||||
|
||||
@@ -14,11 +15,47 @@ type ServerCmdList struct {
|
||||
Pagination
|
||||
}
|
||||
|
||||
var SysServerCmds = []*ServerCmd{
|
||||
{Cmd: "h", Option: "", Explain: "show help"},
|
||||
{Cmd: "relay-servers", Alias: "rs", Option: "<separated by ,>", Explain: "set or show relay servers"},
|
||||
{Cmd: "ip-blocker", Alias: "ib", Option: "[<ip>|<number>] [-]", Explain: "block or unblock ip or show blocked ip"},
|
||||
{Cmd: "ip-changes", Alias: "ic", Option: "[<id>|<number>] [-]", Explain: "ip-changes(ic) [<id>|<number>] [-]"},
|
||||
{Cmd: "always-use-relay(aur)", Alias: "aur", Option: "[y|n]", Explain: "always use relay"},
|
||||
{Cmd: "test-geo", Alias: "tg", Option: "<ip1> <ip2>", Explain: "test geo"},
|
||||
const (
|
||||
ServerCmdTargetIdServer = "21115"
|
||||
ServerCmdTargetRelayServer = "21117"
|
||||
)
|
||||
|
||||
var SysIdServerCmds = []*ServerCmd{
|
||||
{Cmd: "h", Option: "", Explain: "show help", Target: ServerCmdTargetIdServer},
|
||||
{Cmd: "relay-servers", Alias: "rs", Option: "<separated by ,>", Explain: "set or show relay servers", Target: ServerCmdTargetIdServer},
|
||||
{Cmd: "ip-blocker", Alias: "ib", Option: "[<ip>|<number>] [-]", Explain: "block or unblock ip or show blocked ip", Target: ServerCmdTargetIdServer},
|
||||
{Cmd: "ip-changes", Alias: "ic", Option: "[<id>|<number>] [-]", Explain: "ip-changes(ic) [<id>|<number>] [-]", Target: ServerCmdTargetIdServer},
|
||||
{Cmd: "always-use-relay", Alias: "aur", Option: "[y|n]", Explain: "always use relay", Target: ServerCmdTargetIdServer},
|
||||
{Cmd: "test-geo", Alias: "tg", Option: "<ip1> <ip2>", Explain: "test geo", Target: ServerCmdTargetIdServer},
|
||||
}
|
||||
|
||||
/*
|
||||
"blacklist-add(ba) <ip>",
|
||||
"blacklist-remove(br) <ip>",
|
||||
"blacklist(b) <ip>",
|
||||
"blocklist-add(Ba) <ip>",
|
||||
"blocklist-remove(Br) <ip>",
|
||||
"blocklist(B) <ip>",
|
||||
"downgrade-threshold(dt) [value]",
|
||||
"downgrade-start-check(t) [value(second)]",
|
||||
"limit-speed(ls) [value(Mb/s)]",
|
||||
"total-bandwidth(tb) [value(Mb/s)]",
|
||||
"single-bandwidth(sb) [value(Mb/s)]",
|
||||
"usage(u)"
|
||||
*/
|
||||
|
||||
var SysRelayServerCmds = []*ServerCmd{
|
||||
{Cmd: "h", Option: "", Explain: "show help", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "blacklist-add", Alias: "ba", Option: "<ip>", Explain: "blacklist-add(ba) <ip>", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "blacklist-remove", Alias: "br", Option: "<ip>", Explain: "blacklist-remove(br) <ip>", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "blacklist", Alias: "b", Option: "<ip>", Explain: "blacklist(b) <ip>", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "blocklist-add", Alias: "Ba", Option: "<ip>", Explain: "blocklist-add(Ba) <ip>", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "blocklist-remove", Alias: "Br", Option: "<ip>", Explain: "blocklist-remove(Br) <ip>", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "blocklist", Alias: "B", Option: "<ip>", Explain: "blocklist(B) <ip>", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "downgrade-threshold", Alias: "dt", Option: "[value]", Explain: "downgrade-threshold(dt) [value]", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "downgrade-start-check", Alias: "t", Option: "[value(second)]", Explain: "downgrade-start-check(t) [value(second)]", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "limit-speed", Alias: "ls", Option: "[value(Mb/s)]", Explain: "limit-speed(ls) [value(Mb/s)]", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "total-bandwidth", Alias: "tb", Option: "[value(Mb/s)]", Explain: "total-bandwidth(tb) [value(Mb/s)]", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "single-bandwidth", Alias: "sb", Option: "[value(Mb/s)]", Explain: "single-bandwidth(sb) [value(Mb/s)]", Target: ServerCmdTargetRelayServer},
|
||||
{Cmd: "usage", Alias: "u", Option: "", Explain: "usage(u)", Target: ServerCmdTargetRelayServer},
|
||||
}
|
||||
|
||||
@@ -41,15 +41,15 @@ func (is *ServerCmdService) Create(u *model.ServerCmd) error {
|
||||
}
|
||||
|
||||
// SendCmd 发送命令
|
||||
func (is *ServerCmdService) SendCmd(cmd string, arg string) (string, error) {
|
||||
func (is *ServerCmdService) SendCmd(port string, cmd string, arg string) (string, error) {
|
||||
//组装命令
|
||||
cmd = cmd + " " + arg
|
||||
res, err := is.SendSocketCmd("v6", cmd)
|
||||
res, err := is.SendSocketCmd("v6", port, cmd)
|
||||
if err == nil {
|
||||
return res, nil
|
||||
}
|
||||
//v6连接失败,尝试v4
|
||||
res, err = is.SendSocketCmd("v4", cmd)
|
||||
res, err = is.SendSocketCmd("v4", port, cmd)
|
||||
if err == nil {
|
||||
return res, nil
|
||||
}
|
||||
@@ -57,23 +57,23 @@ func (is *ServerCmdService) SendCmd(cmd string, arg string) (string, error) {
|
||||
}
|
||||
|
||||
// SendSocketCmd
|
||||
func (is *ServerCmdService) SendSocketCmd(ty string, cmd string) (string, error) {
|
||||
func (is *ServerCmdService) SendSocketCmd(ty string, port string, cmd string) (string, error) {
|
||||
addr := "[::1]"
|
||||
tcp := "tcp6"
|
||||
if ty == "v4" {
|
||||
tcp = "tcp"
|
||||
addr = "127.0.0.1"
|
||||
}
|
||||
conn, err := net.Dial(tcp, addr+":21115")
|
||||
conn, err := net.Dial(tcp, fmt.Sprintf("%s:%s", addr, port))
|
||||
if err != nil {
|
||||
fmt.Printf("connect to id %s server failed: %v\n", ty, err)
|
||||
global.Logger.Debugf("%s connect to id server failed: %v", ty, err)
|
||||
return "", err
|
||||
}
|
||||
defer conn.Close()
|
||||
//发送命令
|
||||
_, err = conn.Write([]byte(cmd))
|
||||
if err != nil {
|
||||
fmt.Printf("send cmd failed: %v\n", err)
|
||||
global.Logger.Debugf("%s send cmd failed: %v", ty, err)
|
||||
return "", err
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
@@ -81,7 +81,7 @@ func (is *ServerCmdService) SendSocketCmd(ty string, cmd string) (string, error)
|
||||
buf := make([]byte, 1024)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil && err.Error() != "EOF" {
|
||||
fmt.Printf("read response failed: %v\n", err)
|
||||
global.Logger.Debugf("%s read response failed: %v", ty, err)
|
||||
return "", err
|
||||
}
|
||||
return string(buf[:n]), nil
|
||||
|
||||
@@ -68,6 +68,9 @@ func (us *UserService) InfoByAccessToken(token string) (*model.User, *model.User
|
||||
|
||||
// GenerateToken 生成token
|
||||
func (us *UserService) GenerateToken(u *model.User) string {
|
||||
if len(global.Jwt.Key) > 0 {
|
||||
return global.Jwt.GenerateToken(u.Id)
|
||||
}
|
||||
return utils.Md5(u.Username + time.Now().String())
|
||||
}
|
||||
|
||||
@@ -461,3 +464,7 @@ func (us *UserService) AutoRefreshAccessToken(ut *model.UserToken) {
|
||||
func (us *UserService) BatchDeleteUserToken(ids []uint) error {
|
||||
return global.DB.Where("id in ?", ids).Delete(&model.UserToken{}).Error
|
||||
}
|
||||
|
||||
func (us *UserService) VerifyJWT(token string) (uint, error) {
|
||||
return global.Jwt.ParseToken(token)
|
||||
}
|
||||
|
||||