Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c625dd881 | ||
|
|
30194479d1 | ||
|
|
ddeced3540 | ||
|
|
dc43b6973a | ||
|
|
d1013c2416 | ||
|
|
f7be2bc2e6 | ||
|
|
42d1e35913 | ||
|
|
74f512d214 | ||
|
|
b945069117 | ||
|
|
efcbff23d8 | ||
|
|
dcabfb1546 | ||
|
|
9e6d758c0f | ||
|
|
1da20feb06 | ||
|
|
3044c9b735 | ||
|
|
b44e4891a6 |
@@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
# local files
|
# local files
|
||||||
qqwry.dat
|
qqwry.dat
|
||||||
revsuit.db
|
GeoLite2-City.mmdb
|
||||||
revsuit.db-shm
|
*.db
|
||||||
revsuit.db-wal
|
*.db-shm
|
||||||
|
*.db-wal
|
||||||
|
|
||||||
# local config
|
# local config
|
||||||
config.yaml*
|
config.yaml*
|
||||||
@@ -20,3 +21,8 @@ revsuit
|
|||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
|
## node
|
||||||
|
package.json
|
||||||
|
package-lock.json
|
||||||
|
node_modules/
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||||
|
|
||||||
|
### [0.1.5-beta](https://github.com/Li4n0/revsuit/compare/v0.1.4-beta-fix-1...v0.1.5-beta) (2021-06-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **ipinfo:** support GeoIP ([#26](https://github.com/Li4n0/revsuit/issues/26)) ([dc43b69](https://github.com/Li4n0/revsuit/commit/dc43b6973a5ac98e439d1353102ade2029b1d382))
|
||||||
|
* **platform:** support custom admin path prefix ([#25](https://github.com/Li4n0/revsuit/issues/25)) ([f7be2bc](https://github.com/Li4n0/revsuit/commit/f7be2bc2e67841178e9316995999b20f80a49df7))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **frontend:** fix the bug of autoRefresh ([#27](https://github.com/Li4n0/revsuit/issues/27)) ([d1013c2](https://github.com/Li4n0/revsuit/commit/d1013c2416c04bd72b9cbb0c7e6b4b3f2e717837))
|
||||||
|
* **frontend:** fix the frontend display bugs ([#28](https://github.com/Li4n0/revsuit/issues/28)) ([ddeced3](https://github.com/Li4n0/revsuit/commit/ddeced354042e0be6db5dd4feffa13ef22db231f))
|
||||||
|
|
||||||
|
### [0.1.4-beta-fix-1](https://github.com/Li4n0/revsuit/compare/v0.1.4-beta...v0.1.4-beta-fix-1) (2021-05-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **frontend:** fix the problem of autoRefresh failure ([#24](https://github.com/Li4n0/revsuit/issues/24)) ([b945069](https://github.com/Li4n0/revsuit/commit/b945069117fec6eb5de88557da5d4c2c996cfd90))
|
||||||
|
* **http:** fix the problem that ip_header setting does not take effect ([#23](https://github.com/Li4n0/revsuit/issues/23)) ([74f512d](https://github.com/Li4n0/revsuit/commit/74f512d2140fb97128acf56be803d1bd3b888fa3))
|
||||||
|
|
||||||
|
### [0.1.4-beta](https://github.com/Li4n0/revsuit/compare/v0.1.3-beta-fix1...v0.1.4-beta) (2021-05-27)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **dns:** support custom dns service
|
||||||
|
port ([7fb4c97](https://github.com/Li4n0/revsuit/commit/7fb4c97279e57d120a4e4aef5dda5c8f3c024835))
|
||||||
|
* **frontend:** auto refresh data when switching back to the revsuit
|
||||||
|
console ([9b31406](https://github.com/Li4n0/revsuit/commit/9b314062a39ddc7acf7a7eab3570b24b9bb9d122))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **http:** fix the problem that ip_header configuration does not take
|
||||||
|
effect ([b76c39e](https://github.com/Li4n0/revsuit/commit/b76c39e2fc1ada189feb783fdec76daffa11d1c7))
|
||||||
@@ -29,8 +29,10 @@ Download the latest release firstly.
|
|||||||
RevSuit will generate default configuration file on first run. Modify the configuration file according to your needs,
|
RevSuit will generate default configuration file on first run. Modify the configuration file according to your needs,
|
||||||
then re-run.
|
then re-run.
|
||||||
|
|
||||||
To confirm the location of the connection IP, if there is no qqwry.dat in the current directory or its modification time
|
In order to confirm the IP location, you need to use the IP location database. `QQwry` is used as the data source by
|
||||||
is more than 5 days ago. RevSuit will download it.(Support for GeoIP is in the planning stages).
|
default, you can also modify the configuration to use `GeoIP`. If the selected database is not available in the current
|
||||||
|
directory or the database is updated for more than a week, RevSuit will automatically download the latest database. If
|
||||||
|
the download fails, the `IpArea` field will always be null.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ ./revsuit
|
$ ./revsuit
|
||||||
@@ -143,8 +145,8 @@ example.
|
|||||||
|
|
||||||
#### Multi-client
|
#### Multi-client
|
||||||
|
|
||||||
RevSuit supports multiple clients, and each client in the connected state receives a push of `flag`, so distributed
|
As shown above, RevSuit supports multiple clients, and each client in the connected state receives a push of `flag`, so
|
||||||
scanning can be supported.
|
distributed scanning can be supported.
|
||||||
|
|
||||||
#### Temporary storage queue
|
#### Temporary storage queue
|
||||||
|
|
||||||
@@ -213,7 +215,7 @@ the port scan.
|
|||||||
|
|
||||||
The running effect is as follows:
|
The running effect is as follows:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
It because the FTP connection will be crashed if `Passive Address` is not accessible, we can determine whether the port
|
It because the FTP connection will be crashed if `Passive Address` is not accessible, we can determine whether the port
|
||||||
is open or not based on whether the connection exits normally.For this example, we successfully detected that port 8005
|
is open or not based on whether the connection exits normally.For this example, we successfully detected that port 8005
|
||||||
@@ -236,7 +238,7 @@ Submit an issue or contact me through Weixin: `Li4n06`
|
|||||||
|
|
||||||
### Specifically
|
### Specifically
|
||||||
|
|
||||||
Thanks to my friend [@E99plant](https://github.com/wuhan005/) for all the help and advice I received during the
|
Thanks to my friend [@E99p1ant](https://github.com/wuhan005/) for all the help and advice I received during the
|
||||||
development of this project.
|
development of this project.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
.custom-icons-list[data-v-05a908c2] .anticon{margin-right:6px}body[data-v-07ed630b],html[data-v-07ed630b]{height:100%;margin:0}.fade-transform-enter-active[data-v-07ed630b],.fade-transform-leave-active[data-v-07ed630b]{transition:all .3s;opacity:0}.fade-transform-enter[data-v-07ed630b],.fade-transform-leave[data-v-07ed630b]{opacity:0}.fade-transform-enter-to[data-v-07ed630b]{opacity:0}.ant-menu-item>span>a[data-v-07ed630b]{color:hsla(0,0%,100%,.65)}.ant-menu-item-selected>span>a[data-v-07ed630b]{color:#fff}#nav[data-v-07ed630b]{height:100%}#nav .trigger[data-v-07ed630b]{font-size:18px;line-height:64px;padding:0 24px;cursor:pointer;transition:color .3s}#nav .trigger[data-v-07ed630b]:hover{color:#1890ff}#nav .logo[data-v-07ed630b]{height:32px;background:#0a1d2d;margin:16px;text-align:center;font-size:1.2rem;color:#fff;padding-bottom:5px;border-bottom:2px solid #b6befa}.copyright[data-v-07ed630b]{color:#888;text-align:right;margin-right:1rem}
|
.custom-icons-list[data-v-05a908c2] .anticon{margin-right:6px}body[data-v-1bc6d13e],html[data-v-1bc6d13e]{height:100%;margin:0}.fade-transform-enter-active[data-v-1bc6d13e],.fade-transform-leave-active[data-v-1bc6d13e]{transition:all .3s;opacity:0}.fade-transform-enter[data-v-1bc6d13e],.fade-transform-leave[data-v-1bc6d13e]{opacity:0}.fade-transform-enter-to[data-v-1bc6d13e]{opacity:0}.ant-menu-item>span>a[data-v-1bc6d13e]{color:hsla(0,0%,100%,.65)}.ant-menu-item-selected>span>a[data-v-1bc6d13e]{color:#fff}#app[data-v-1bc6d13e]{min-height:100%}#app .trigger[data-v-1bc6d13e]{font-size:18px;line-height:64px;padding:0 24px;cursor:pointer;transition:color .3s}#app .trigger[data-v-1bc6d13e]:hover{color:#1890ff}#app .logo[data-v-1bc6d13e]{height:32px;background:#0a1d2d;margin:16px;text-align:center;font-size:1.2rem;color:#fff;padding-bottom:5px;border-bottom:2px solid #b6befa}.copyright[data-v-1bc6d13e]{color:#888;text-align:right;margin-right:1rem}
|
||||||
@@ -1 +1 @@
|
|||||||
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>RevSuit Control Panel</title><link href="css/chunk-016c45cf.css" rel="prefetch"><link href="css/chunk-0cb5e9e6.css" rel="prefetch"><link href="css/chunk-1da7f23b.css" rel="prefetch"><link href="css/chunk-247d6284.css" rel="prefetch"><link href="css/chunk-330a7e95.css" rel="prefetch"><link href="css/chunk-3d13e56e.css" rel="prefetch"><link href="css/chunk-43748c28.css" rel="prefetch"><link href="css/chunk-49fbda44.css" rel="prefetch"><link href="css/chunk-e039e75a.css" rel="prefetch"><link href="css/chunk-fef965c2.css" rel="prefetch"><link href="js/chunk-016c45cf.js" rel="prefetch"><link href="js/chunk-08f9fbe8.js" rel="prefetch"><link href="js/chunk-0cb5e9e6.js" rel="prefetch"><link href="js/chunk-1da7f23b.js" rel="prefetch"><link href="js/chunk-247d6284.js" rel="prefetch"><link href="js/chunk-330a7e95.js" rel="prefetch"><link href="js/chunk-3d13e56e.js" rel="prefetch"><link href="js/chunk-43748c28.js" rel="prefetch"><link href="js/chunk-49fbda44.js" rel="prefetch"><link href="js/chunk-b241c712.js" rel="prefetch"><link href="js/chunk-e039e75a.js" rel="prefetch"><link href="js/chunk-fef965c2.js" rel="prefetch"><link href="css/app.css" rel="preload" as="style"><link href="css/chunk-vendors.css" rel="preload" as="style"><link href="js/app.js" rel="preload" as="script"><link href="js/chunk-vendors.js" rel="preload" as="script"><link href="css/chunk-vendors.css" rel="stylesheet"><link href="css/app.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but revsuit-frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.js"></script><script src="js/app.js"></script></body></html>
|
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>RevSuit Control Panel</title><link href="/revsuit/admin/css/chunk-016c45cf.css" rel="prefetch"><link href="/revsuit/admin/css/chunk-0cb5e9e6.css" rel="prefetch"><link href="/revsuit/admin/css/chunk-193ec343.css" rel="prefetch"><link href="/revsuit/admin/css/chunk-36508a38.css" rel="prefetch"><link href="/revsuit/admin/css/chunk-43748c28.css" rel="prefetch"><link href="/revsuit/admin/css/chunk-46a53d26.css" rel="prefetch"><link href="/revsuit/admin/css/chunk-49fbda44.css" rel="prefetch"><link href="/revsuit/admin/css/chunk-5fb70d83.css" rel="prefetch"><link href="/revsuit/admin/css/chunk-72839f90.css" rel="prefetch"><link href="/revsuit/admin/css/chunk-740736c7.css" rel="prefetch"><link href="/revsuit/admin/js/chunk-016c45cf.js" rel="prefetch"><link href="/revsuit/admin/js/chunk-0cb5e9e6.js" rel="prefetch"><link href="/revsuit/admin/js/chunk-193ec343.js" rel="prefetch"><link href="/revsuit/admin/js/chunk-27186dd0.js" rel="prefetch"><link href="/revsuit/admin/js/chunk-36508a38.js" rel="prefetch"><link href="/revsuit/admin/js/chunk-43748c28.js" rel="prefetch"><link href="/revsuit/admin/js/chunk-46a53d26.js" rel="prefetch"><link href="/revsuit/admin/js/chunk-49fbda44.js" rel="prefetch"><link href="/revsuit/admin/js/chunk-5fb70d83.js" rel="prefetch"><link href="/revsuit/admin/js/chunk-72839f90.js" rel="prefetch"><link href="/revsuit/admin/js/chunk-740736c7.js" rel="prefetch"><link href="/revsuit/admin/js/chunk-b241c712.js" rel="prefetch"><link href="/revsuit/admin/css/app.css" rel="preload" as="style"><link href="/revsuit/admin/css/chunk-vendors.css" rel="preload" as="style"><link href="/revsuit/admin/js/app.js" rel="preload" as="script"><link href="/revsuit/admin/js/chunk-vendors.js" rel="preload" as="script"><link href="/revsuit/admin/css/chunk-vendors.css" rel="stylesheet"><link href="/revsuit/admin/css/app.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but revsuit-frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/revsuit/admin/js/chunk-vendors.js"></script><script src="/revsuit/admin/js/app.js"></script></body></html>
|
||||||
@@ -5,13 +5,15 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
|
"name": "revsuit-frontend",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ant-design-vue": "^1.2.4",
|
"ant-design-vue": "^1.2.4",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-router": "^3.2.0"
|
"vue-router": "^3.2.0",
|
||||||
|
"vue-visibility-change": "^1.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/cli-plugin-babel": "~4.5.0",
|
||||||
@@ -4808,7 +4810,8 @@
|
|||||||
"node_modules/de-indent": {
|
"node_modules/de-indent": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/de-indent/download/de-indent-1.0.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/de-indent/download/de-indent-1.0.2.tgz",
|
||||||
"integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
|
"integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
@@ -6896,6 +6899,7 @@
|
|||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/he/download/he-1.2.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/he/download/he-1.2.0.tgz",
|
||||||
"integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=",
|
"integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=",
|
||||||
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"he": "bin/he"
|
"he": "bin/he"
|
||||||
}
|
}
|
||||||
@@ -13517,6 +13521,7 @@
|
|||||||
"version": "2.6.12",
|
"version": "2.6.12",
|
||||||
"resolved": "https://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.6.12.tgz",
|
"resolved": "https://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.6.12.tgz",
|
||||||
"integrity": "sha1-lH7XGWdEyKUoXr4SM/6WBDf8xX4=",
|
"integrity": "sha1-lH7XGWdEyKUoXr4SM/6WBDf8xX4=",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"de-indent": "^1.0.2",
|
"de-indent": "^1.0.2",
|
||||||
"he": "^1.1.0"
|
"he": "^1.1.0"
|
||||||
@@ -13528,6 +13533,11 @@
|
|||||||
"integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
|
"integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/vue-visibility-change": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/vue-visibility-change/download/vue-visibility-change-1.2.1.tgz",
|
||||||
|
"integrity": "sha1-0YAIv08d4slHr+VEHuBEuenGAUE="
|
||||||
|
},
|
||||||
"node_modules/warning": {
|
"node_modules/warning": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npm.taobao.org/warning/download/warning-4.0.3.tgz",
|
"resolved": "https://registry.npm.taobao.org/warning/download/warning-4.0.3.tgz",
|
||||||
@@ -16426,8 +16436,7 @@
|
|||||||
"version": "4.5.11",
|
"version": "4.5.11",
|
||||||
"resolved": "https://registry.npm.taobao.org/@vue/cli-plugin-vuex/download/@vue/cli-plugin-vuex-4.5.11.tgz?cache=0&sync_timestamp=1615453605559&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fcli-plugin-vuex%2Fdownload%2F%40vue%2Fcli-plugin-vuex-4.5.11.tgz",
|
"resolved": "https://registry.npm.taobao.org/@vue/cli-plugin-vuex/download/@vue/cli-plugin-vuex-4.5.11.tgz?cache=0&sync_timestamp=1615453605559&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fcli-plugin-vuex%2Fdownload%2F%40vue%2Fcli-plugin-vuex-4.5.11.tgz",
|
||||||
"integrity": "sha1-9vYZvPtmyGzEU0DXMVKERjXlSL0=",
|
"integrity": "sha1-9vYZvPtmyGzEU0DXMVKERjXlSL0=",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"@vue/cli-service": {
|
"@vue/cli-service": {
|
||||||
"version": "4.5.11",
|
"version": "4.5.11",
|
||||||
@@ -16581,8 +16590,7 @@
|
|||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/@vue/preload-webpack-plugin/download/@vue/preload-webpack-plugin-1.1.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/@vue/preload-webpack-plugin/download/@vue/preload-webpack-plugin-1.1.2.tgz",
|
||||||
"integrity": "sha1-zrkktOyzucQ4ccekKaAvhCPmIas=",
|
"integrity": "sha1-zrkktOyzucQ4ccekKaAvhCPmIas=",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"@vue/web-component-wrapper": {
|
"@vue/web-component-wrapper": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
@@ -16797,8 +16805,7 @@
|
|||||||
"version": "5.3.1",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/acorn-jsx/download/acorn-jsx-5.3.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/acorn-jsx/download/acorn-jsx-5.3.1.tgz",
|
||||||
"integrity": "sha1-/IZh4Rt6wVOcR9v+oucrOvNNJns=",
|
"integrity": "sha1-/IZh4Rt6wVOcR9v+oucrOvNNJns=",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"acorn-walk": {
|
"acorn-walk": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
@@ -16846,15 +16853,13 @@
|
|||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/ajv-errors/download/ajv-errors-1.0.1.tgz?cache=0&sync_timestamp=1615411237786&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-errors%2Fdownload%2Fajv-errors-1.0.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/ajv-errors/download/ajv-errors-1.0.1.tgz?cache=0&sync_timestamp=1615411237786&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-errors%2Fdownload%2Fajv-errors-1.0.1.tgz",
|
||||||
"integrity": "sha1-81mGrOuRr63sQQL72FAUlQzvpk0=",
|
"integrity": "sha1-81mGrOuRr63sQQL72FAUlQzvpk0=",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"ajv-keywords": {
|
"ajv-keywords": {
|
||||||
"version": "3.5.2",
|
"version": "3.5.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz?cache=0&sync_timestamp=1615647295573&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz?cache=0&sync_timestamp=1615647295573&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.2.tgz",
|
||||||
"integrity": "sha1-MfKdpatuANHC0yms97WSlhTVAU0=",
|
"integrity": "sha1-MfKdpatuANHC0yms97WSlhTVAU0=",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"alphanum-sort": {
|
"alphanum-sort": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@@ -18894,7 +18899,8 @@
|
|||||||
"de-indent": {
|
"de-indent": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/de-indent/download/de-indent-1.0.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/de-indent/download/de-indent-1.0.2.tgz",
|
||||||
"integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
|
"integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
@@ -20627,7 +20633,8 @@
|
|||||||
"he": {
|
"he": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/he/download/he-1.2.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/he/download/he-1.2.0.tgz",
|
||||||
"integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8="
|
"integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"hex-color-regex": {
|
"hex-color-regex": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
@@ -26181,6 +26188,7 @@
|
|||||||
"version": "2.6.12",
|
"version": "2.6.12",
|
||||||
"resolved": "https://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.6.12.tgz",
|
"resolved": "https://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.6.12.tgz",
|
||||||
"integrity": "sha1-lH7XGWdEyKUoXr4SM/6WBDf8xX4=",
|
"integrity": "sha1-lH7XGWdEyKUoXr4SM/6WBDf8xX4=",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"de-indent": "^1.0.2",
|
"de-indent": "^1.0.2",
|
||||||
"he": "^1.1.0"
|
"he": "^1.1.0"
|
||||||
@@ -26192,6 +26200,11 @@
|
|||||||
"integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
|
"integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"vue-visibility-change": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/vue-visibility-change/download/vue-visibility-change-1.2.1.tgz",
|
||||||
|
"integrity": "sha1-0YAIv08d4slHr+VEHuBEuenGAUE="
|
||||||
|
},
|
||||||
"warning": {
|
"warning": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npm.taobao.org/warning/download/warning-4.0.3.tgz",
|
"resolved": "https://registry.npm.taobao.org/warning/download/warning-4.0.3.tgz",
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-router": "^3.2.0"
|
"vue-router": "^3.2.0",
|
||||||
|
"vue-visibility-change": "^1.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/cli-plugin-babel": "~4.5.0",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-layout id="nav">
|
<a-layout id="app" v-visibility-change="()=>{this.$refs.content.fetch?this.$refs.content.fetch():null}">
|
||||||
<a-layout-sider v-model="collapsed" :trigger="null" collapsible>
|
<a-layout-sider v-model="collapsed" :trigger="null" collapsible>
|
||||||
<div class="logo"><b>R</b><span v-if="!collapsed"><b>ev</b>Suit</span></div>
|
<div class="logo"><b>R</b><span v-if="!collapsed"><b>ev</b>Suit</span></div>
|
||||||
<a-menu theme="dark" mode="inline" :selectedKeys="[this.$route.path]" :openKeys.sync="openKeys">
|
<a-menu theme="dark" mode="inline" :selectedKeys="[this.$route.path]" :openKeys.sync="openKeys">
|
||||||
@@ -151,9 +151,6 @@ export default {
|
|||||||
if (localStorage.getItem("autoRefresh") === null) {
|
if (localStorage.getItem("autoRefresh") === null) {
|
||||||
this.autoRefresh = true;
|
this.autoRefresh = true;
|
||||||
}
|
}
|
||||||
if (this.autoRefresh && this.isLogMode) {
|
|
||||||
this.timing()
|
|
||||||
}
|
|
||||||
this.GetVersion()
|
this.GetVersion()
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@@ -177,8 +174,10 @@ export default {
|
|||||||
localStorage.setItem('autoRefresh', val)
|
localStorage.setItem('autoRefresh', val)
|
||||||
},
|
},
|
||||||
isLogMode(val) {
|
isLogMode(val) {
|
||||||
if (!val) {
|
if (!val && this.timer) {
|
||||||
clearInterval(this.timer)
|
clearInterval(this.timer)
|
||||||
|
} else if (this.autoRefresh) {
|
||||||
|
this.timing()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
refreshInterval(val) {
|
refreshInterval(val) {
|
||||||
@@ -247,11 +246,11 @@ html, body {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
#nav {
|
#app {
|
||||||
height: 100%;
|
min-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#nav .trigger {
|
#app .trigger {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
line-height: 64px;
|
line-height: 64px;
|
||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
@@ -259,11 +258,11 @@ html, body {
|
|||||||
transition: color 0.3s;
|
transition: color 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
#nav .trigger:hover {
|
#app .trigger:hover {
|
||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#nav .logo {
|
#app .logo {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
background: #0a1d2d;
|
background: #0a1d2d;
|
||||||
margin: 16px;
|
margin: 16px;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import axios from 'axios'
|
|||||||
import {store} from "@/main";
|
import {store} from "@/main";
|
||||||
|
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: '/revsuit/api/', // api的base_url
|
baseURL: location.pathname.slice(0, -'/admin/'.length) + "/api", // api的base_url
|
||||||
timeout: 5000, // request timeout
|
timeout: 5000, // request timeout
|
||||||
validateStatus: function (status) {
|
validateStatus: function (status) {
|
||||||
if (status === 403) {
|
if (status === 403) {
|
||||||
|
|||||||
@@ -17,7 +17,8 @@
|
|||||||
<a-select-option value='error'>ERROR</a-select-option>
|
<a-select-option value='error'>ERROR</a-select-option>
|
||||||
<a-select-option value='fatal'>FATAL</a-select-option>
|
<a-select-option value='fatal'>FATAL</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-input :disabled="key ==='Addr' && parent==='Http'" v-else v-model="form[key]"/>
|
<a-input :disabled="(key ==='Addr'||key==='AdminPathPrefix') && parent==='Http'" v-else
|
||||||
|
v-model="form[key]"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
|||||||
@@ -4,10 +4,14 @@ import App from './App';
|
|||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import 'ant-design-vue/dist/antd.css';
|
import 'ant-design-vue/dist/antd.css';
|
||||||
import '@/utils/index'
|
import '@/utils/index'
|
||||||
|
import visibility from 'vue-visibility-change';
|
||||||
|
|
||||||
|
|
||||||
Vue.config.productionTip = false;
|
Vue.config.productionTip = false;
|
||||||
|
|
||||||
Vue.use(Antd);
|
Vue.use(Antd);
|
||||||
|
Vue.use(visibility);
|
||||||
|
|
||||||
export const store = Vue.observable({
|
export const store = Vue.observable({
|
||||||
authed: true,
|
authed: true,
|
||||||
pageSize: localStorage.getItem("pageSize") ? parseInt(localStorage.getItem("pageSize")) : 10
|
pageSize: localStorage.getItem("pageSize") ? parseInt(localStorage.getItem("pageSize")) : 10
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ module.exports = {
|
|||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://localhost:10000',
|
target: 'http://localhost:10000',
|
||||||
pathRewrite: {
|
pathRewrite: {
|
||||||
'^/revsuit/api': '/revsuit/api'
|
'^/api': '/revsuit/api'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
productionSourceMap:false,
|
productionSourceMap: false,
|
||||||
runtimeCompiler: true,
|
runtimeCompiler: true,
|
||||||
filenameHashing: false,
|
filenameHashing: false,
|
||||||
publicPath: ''
|
publicPath: '/revsuit/admin/',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,17 +15,17 @@ require (
|
|||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.6 // indirect
|
github.com/mattn/go-sqlite3 v1.14.6 // indirect
|
||||||
github.com/miekg/dns v1.1.38
|
github.com/miekg/dns v1.1.38
|
||||||
|
github.com/oschwald/geoip2-golang v1.5.0
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sinlov/qqwry-golang v0.0.0-20191204062238-bea9868bbbf4
|
github.com/sinlov/qqwry-golang v0.0.0-20191204062238-bea9868bbbf4
|
||||||
github.com/stretchr/testify v1.6.1
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/ugorji/go v1.2.4 // indirect
|
github.com/ugorji/go v1.2.4 // indirect
|
||||||
github.com/urfave/cli/v2 v2.3.0
|
github.com/urfave/cli/v2 v2.3.0
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
||||||
golang.org/x/sys v0.0.0-20210217105451-b926d437f341 // indirect
|
golang.org/x/sys v0.0.0-20210217105451-b926d437f341 // indirect
|
||||||
google.golang.org/protobuf v1.25.0 // indirect
|
google.golang.org/protobuf v1.25.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
||||||
gorm.io/driver/sqlite v1.1.4
|
gorm.io/driver/sqlite v1.1.4
|
||||||
gorm.io/gorm v1.21.4
|
gorm.io/gorm v1.21.4
|
||||||
|
|||||||
@@ -427,6 +427,10 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
|
|||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02/go.mod h1:JNdpVEzCpXBgIiv4ds+TzhN1hrtxq6ClLrTlT9OQRSc=
|
github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02/go.mod h1:JNdpVEzCpXBgIiv4ds+TzhN1hrtxq6ClLrTlT9OQRSc=
|
||||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
|
github.com/oschwald/geoip2-golang v1.5.0 h1:igg2yQIrrcRccB1ytFXqBfOHCjXWIoMv85lVJ1ONZzw=
|
||||||
|
github.com/oschwald/geoip2-golang v1.5.0/go.mod h1:xdvYt5xQzB8ORWFqPnqMwZpCpgNagttWdoZLlJQzg7s=
|
||||||
|
github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk=
|
||||||
|
github.com/oschwald/maxminddb-golang v1.8.0/go.mod h1:RXZtst0N6+FY/3qCNmZMBApR19cdQj43/NM9VkrNAis=
|
||||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
@@ -518,8 +522,9 @@ github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRci
|
|||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tchap/go-patricia v0.0.0-20160729071656-dd168db6051b/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
github.com/tchap/go-patricia v0.0.0-20160729071656-dd168db6051b/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||||
github.com/tebeka/selenium v0.9.9/go.mod h1:5Fr8+pUvU6B1OiPfkdCKdXZyr5znvVkxuPd0NOdZCQc=
|
github.com/tebeka/selenium v0.9.9/go.mod h1:5Fr8+pUvU6B1OiPfkdCKdXZyr5znvVkxuPd0NOdZCQc=
|
||||||
@@ -668,6 +673,7 @@ golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 174 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 895 KiB After Width: | Height: | Size: 764 KiB |
@@ -1,15 +1,21 @@
|
|||||||
version: 1.0
|
version: 1.3
|
||||||
addr: :10000
|
addr: :10000
|
||||||
token:
|
token:
|
||||||
domain:
|
domain:
|
||||||
external_ip: # You need to make sure that your target can access the server through this ip.
|
external_ip: # You need to make sure that your target can access the server through this ip.
|
||||||
|
admin_path_prefix: "/revsuit"
|
||||||
database: revsuit.db
|
database: revsuit.db
|
||||||
log_level: info
|
log_level: info
|
||||||
|
|
||||||
|
ip_location_database:
|
||||||
|
database: "qqwry" # qqwry or geoip.
|
||||||
|
geo_license_key: "" # Mandatory field, if you choose to use GeoIP.
|
||||||
|
|
||||||
http:
|
http:
|
||||||
ip_header:
|
ip_header:
|
||||||
dns:
|
dns:
|
||||||
enable: true
|
enable: true
|
||||||
|
addr: :53
|
||||||
rmi:
|
rmi:
|
||||||
enable: true
|
enable: true
|
||||||
addr: :1099
|
addr: :1099
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package ipinfo
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Database string
|
||||||
|
GeoLicenseKey string `yaml:"geo_license_key"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package ipinfo
|
||||||
|
|
||||||
|
type Database interface {
|
||||||
|
Area(string) string
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package geoip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "unknwon.dev/clog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Url = "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=%s&suffix=tar.gz"
|
||||||
|
)
|
||||||
|
|
||||||
|
func get(url string) (b []byte, err error) {
|
||||||
|
client := http.Client{
|
||||||
|
Timeout: 90 * time.Second,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // disable verify
|
||||||
|
}}
|
||||||
|
request, _ := http.NewRequest(http.MethodGet, url, nil)
|
||||||
|
request.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36")
|
||||||
|
|
||||||
|
resp, err := client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
return io.ReadAll(resp.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractTarGz(gzipStream io.Reader) error {
|
||||||
|
uncompressedStream, err := gzip.NewReader(gzipStream)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tarReader := tar.NewReader(uncompressedStream)
|
||||||
|
|
||||||
|
for {
|
||||||
|
header, err := tarReader.Next()
|
||||||
|
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch header.Typeflag {
|
||||||
|
case tar.TypeReg:
|
||||||
|
log.Trace(header.Name)
|
||||||
|
if !strings.HasSuffix(header.Name, "GeoLite2-City.mmdb") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
outFile, err := os.Create("GeoLite2-City.mmdb")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer outFile.Close()
|
||||||
|
if _, err := io.Copy(outFile, tarReader); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func download(licenseKey string) (err error) {
|
||||||
|
var GeoLite2TarGz []byte
|
||||||
|
log.Info("Downloading GeoLite2-City.mmdb...")
|
||||||
|
if GeoLite2TarGz, err = get(fmt.Sprintf(Url, licenseKey)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return extractTarGz(bytes.NewReader(GeoLite2TarGz))
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package geoip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/oschwald/geoip2-golang"
|
||||||
|
log "unknwon.dev/clog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Database struct {
|
||||||
|
geo *geoip2.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
var geo *geoip2.Reader
|
||||||
|
var once sync.Once
|
||||||
|
|
||||||
|
// Area returns IpArea according to ip
|
||||||
|
func (db *Database) Area(ip string) string {
|
||||||
|
defer func() {
|
||||||
|
_ = recover()
|
||||||
|
}()
|
||||||
|
record, err := db.geo.City(net.ParseIP(ip))
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
country := record.Country.Names["en"]
|
||||||
|
city := record.City.Names["en"]
|
||||||
|
if city == "" {
|
||||||
|
city = record.Location.TimeZone
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s %s", country, city)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkUpdate(licenseKey string) {
|
||||||
|
info, err := os.Stat("GeoLite2-City.mmdb")
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
err := download(licenseKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Download GeoLite2-City.mmdb failed, caused by:%v, recommend to download it by yourself otherwise the `IpArea` will be null", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if -time.Until(info.ModTime()) > 7*24*time.Hour {
|
||||||
|
log.Info("Updating GeoLite2-City.mmdb...")
|
||||||
|
err := download(licenseKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Update GeoLite2-City.mmdb failed, please download GeoLite2-City.mmdb by yourself")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(licenseKey string) *Database {
|
||||||
|
once.Do(func() {
|
||||||
|
var err error
|
||||||
|
checkUpdate(licenseKey)
|
||||||
|
geo, err = geoip2.Open("GeoLite2-City.mmdb")
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Load GeoLite2-City.mmdb failed, `IpArea` will be null")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return &Database{geo: geo}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package ipinfo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/li4n0/revsuit/internal/ipinfo/geoip"
|
||||||
|
"github.com/li4n0/revsuit/internal/ipinfo/qqwry"
|
||||||
|
log "unknwon.dev/clog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var db Database
|
||||||
|
|
||||||
|
func Area(ip string) string {
|
||||||
|
if db != nil {
|
||||||
|
return db.Area(ip)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init(config Config) {
|
||||||
|
switch config.Database {
|
||||||
|
case "qqwry":
|
||||||
|
db = qqwry.New()
|
||||||
|
case "geoip":
|
||||||
|
db = geoip.New(config.GeoLicenseKey)
|
||||||
|
default:
|
||||||
|
log.Fatal("wrong ip location database type: %q", config.Database)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,8 +6,9 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
CopyWriteUrl = "https://qqwry.mirror.noc.one/copywrite.rar"
|
CopyWriteUrl = "https://qqwry.mirror.noc.one/copywrite.rar"
|
||||||
QqwryUrl = "https://qqwry.mirror.noc.one/qqwry.rar"
|
Url = "https://qqwry.mirror.noc.one/qqwry.rar"
|
||||||
)
|
)
|
||||||
|
|
||||||
func get(url string) (b []byte, err error) {
|
func get(url string) (b []byte, err error) {
|
||||||
@@ -34,8 +35,7 @@ func get(url string) (b []byte, err error) {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
b, err = ioutil.ReadAll(resp.Body)
|
return io.ReadAll(resp.Body)
|
||||||
return b, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getKey(b []byte) (key uint32, err error) {
|
func getKey(b []byte) (key uint32, err error) {
|
||||||
@@ -58,15 +58,17 @@ func decrypt(b []byte, key uint32) (_ []byte, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
return ioutil.ReadAll(rc)
|
return io.ReadAll(rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func download() (err error) {
|
func download() (err error) {
|
||||||
var (
|
var (
|
||||||
copyWriteData, qqwryData []byte
|
copyWriteData, qqwryData []byte
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
key uint32
|
||||||
)
|
)
|
||||||
log.Info("Downloading qqwry.dat...")
|
log.Info("Downloading qqwry.dat...")
|
||||||
|
|
||||||
wg.Add(2)
|
wg.Add(2)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
@@ -77,23 +79,21 @@ func download() (err error) {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if qqwryData, err = get(QqwryUrl); err != nil {
|
if qqwryData, err = get(Url); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var key uint32
|
|
||||||
if key, err = getKey(copyWriteData); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b, err := decrypt(qqwryData, key)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_ = ioutil.WriteFile("qqwry.dat", b, 0644)
|
|
||||||
|
|
||||||
return nil
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if key, err = getKey(copyWriteData); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if b, err := decrypt(qqwryData, key); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return os.WriteFile("qqwry.dat", b, 0644)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,14 +9,29 @@ import (
|
|||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Database struct {
|
||||||
|
wry *qqwry.QQwry
|
||||||
|
}
|
||||||
|
|
||||||
|
// Area returns IpArea according to ip
|
||||||
|
func (db *Database) Area(ip string) string {
|
||||||
|
defer func() {
|
||||||
|
_ = recover()
|
||||||
|
}()
|
||||||
|
if db.wry == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
ipData := db.wry.SearchByIPv4(ip)
|
||||||
|
if ipData.Area == " CZ88.NET" {
|
||||||
|
return ipData.Country
|
||||||
|
}
|
||||||
|
return ipData.Country + " " + ipData.Area
|
||||||
|
}
|
||||||
|
|
||||||
var wry *qqwry.QQwry
|
var wry *qqwry.QQwry
|
||||||
var once sync.Once
|
var once sync.Once
|
||||||
|
|
||||||
func init() {
|
func checkUpdate() {
|
||||||
_ = log.NewConsole(100,
|
|
||||||
log.ConsoleConfig{
|
|
||||||
Level: log.LevelInfo,
|
|
||||||
})
|
|
||||||
info, err := os.Stat("qqwry.dat")
|
info, err := os.Stat("qqwry.dat")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
@@ -25,7 +40,7 @@ func init() {
|
|||||||
log.Warn("Download qqwry.dat failed, caused by:%v, recommend to download it by yourself otherwise the `IpArea` will be null", err)
|
log.Warn("Download qqwry.dat failed, caused by:%v, recommend to download it by yourself otherwise the `IpArea` will be null", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if -time.Until(info.ModTime()) > 5*24*time.Hour {
|
} else if -time.Until(info.ModTime()) > 7*24*time.Hour {
|
||||||
log.Info("Updating qqwry.dat...")
|
log.Info("Updating qqwry.dat...")
|
||||||
err := download()
|
err := download()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -34,8 +49,9 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetQQWry() *qqwry.QQwry {
|
func New() *Database {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
|
checkUpdate()
|
||||||
qqwry.DatData.FilePath = "qqwry.dat"
|
qqwry.DatData.FilePath = "qqwry.dat"
|
||||||
init := qqwry.DatData.InitDatFile()
|
init := qqwry.DatData.InitDatFile()
|
||||||
if v, ok := init.(error); ok {
|
if v, ok := init.(error); ok {
|
||||||
@@ -46,6 +62,5 @@ func GetQQWry() *qqwry.QQwry {
|
|||||||
}
|
}
|
||||||
wry = qqwry.NewQQwry()
|
wry = qqwry.NewQQwry()
|
||||||
})
|
})
|
||||||
|
return &Database{wry: wry}
|
||||||
return wry
|
|
||||||
}
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package qqwry
|
|
||||||
|
|
||||||
// Area returns IpArea according to ip
|
|
||||||
func Area(ip string) string {
|
|
||||||
defer func() {
|
|
||||||
_ = recover()
|
|
||||||
}()
|
|
||||||
if GetQQWry() == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
ipData := GetQQWry().SearchByIPv4(ip)
|
|
||||||
if ipData.Area == " CZ88.NET" {
|
|
||||||
return ipData.Country
|
|
||||||
}
|
|
||||||
return ipData.Country + " " + ipData.Area
|
|
||||||
}
|
|
||||||
@@ -2,4 +2,5 @@ package dns
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Enable bool
|
Enable bool
|
||||||
|
Addr string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/li4n0/revsuit/internal/database"
|
"github.com/li4n0/revsuit/internal/database"
|
||||||
|
"github.com/li4n0/revsuit/internal/ipinfo"
|
||||||
"github.com/li4n0/revsuit/internal/newdns"
|
"github.com/li4n0/revsuit/internal/newdns"
|
||||||
"github.com/li4n0/revsuit/internal/qqwry"
|
|
||||||
"github.com/li4n0/revsuit/internal/recycler"
|
"github.com/li4n0/revsuit/internal/recycler"
|
||||||
"github.com/li4n0/revsuit/internal/rule"
|
"github.com/li4n0/revsuit/internal/rule"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
@@ -135,7 +135,7 @@ func (s *Server) newZone(name string) *newdns.Zone {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := newRecord(_rule, flag, domain, ip, qqwry.Area(ip))
|
r, err := newRecord(_rule, flag, domain, ip, ipinfo.Area(ip))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("DNS record(rule_id:%s) created failed :%s", _rule.Name, err)
|
log.Warn("DNS record(rule_id:%s) created failed :%s", _rule.Name, err)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -252,7 +252,7 @@ func (s *Server) Run() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err := server.Run(":53")
|
err := server.Run(s.Addr)
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -47,16 +47,17 @@ func ListRecords(c *gin.Context) {
|
|||||||
res []Record
|
res []Record
|
||||||
count int64
|
count int64
|
||||||
order = c.Query("order")
|
order = c.Query("order")
|
||||||
pageSize int
|
pageSize = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Query("pageSize") == "" {
|
if c.Query("pageSize") != "" {
|
||||||
pageSize = 10
|
if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
||||||
} else if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
if n > 0 && n < 100 {
|
||||||
if n <= 0 || n > 100 {
|
pageSize = n
|
||||||
pageSize = 10
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.ShouldBind(&dnsRecord); err != nil {
|
if err := c.ShouldBind(&dnsRecord); err != nil {
|
||||||
c.JSON(400, gin.H{
|
c.JSON(400, gin.H{
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
|
|||||||
@@ -80,14 +80,14 @@ func ListRules(c *gin.Context) {
|
|||||||
res []Rule
|
res []Rule
|
||||||
count int64
|
count int64
|
||||||
order = c.Query("order")
|
order = c.Query("order")
|
||||||
pageSize int
|
pageSize = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Query("pageSize") == "" {
|
if c.Query("pageSize") != "" {
|
||||||
pageSize = 10
|
if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
||||||
} else if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
if n > 0 && n < 100 {
|
||||||
if n <= 0 || n > 100 {
|
pageSize = n
|
||||||
pageSize = 10
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/li4n0/revsuit/internal/database"
|
"github.com/li4n0/revsuit/internal/database"
|
||||||
"github.com/li4n0/revsuit/internal/file"
|
"github.com/li4n0/revsuit/internal/file"
|
||||||
|
"github.com/li4n0/revsuit/internal/ipinfo"
|
||||||
"github.com/li4n0/revsuit/internal/notice"
|
"github.com/li4n0/revsuit/internal/notice"
|
||||||
"github.com/li4n0/revsuit/internal/qqwry"
|
|
||||||
"github.com/li4n0/revsuit/internal/record"
|
"github.com/li4n0/revsuit/internal/record"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
)
|
)
|
||||||
@@ -59,14 +59,14 @@ func ListRecords(c *gin.Context) {
|
|||||||
res []Record
|
res []Record
|
||||||
count int64
|
count int64
|
||||||
order = c.Query("order")
|
order = c.Query("order")
|
||||||
pageSize int
|
pageSize = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Query("pageSize") == "" {
|
if c.Query("pageSize") != "" {
|
||||||
pageSize = 10
|
if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
||||||
} else if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
if n > 0 && n < 100 {
|
||||||
if n <= 0 || n > 100 {
|
pageSize = n
|
||||||
pageSize = 10
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ func ListRecords(c *gin.Context) {
|
|||||||
|
|
||||||
func createRecord(_rule *Rule, flag, flagGroup, user, password, method, path, filename, ip string, uploadData []byte, status Status) {
|
func createRecord(_rule *Rule, flag, flagGroup, user, password, method, path, filename, ip string, uploadData []byte, status Status) {
|
||||||
// create new record
|
// create new record
|
||||||
area := qqwry.Area(ip)
|
area := ipinfo.Area(ip)
|
||||||
var ftpFile *file.FTPFile
|
var ftpFile *file.FTPFile
|
||||||
var r *Record
|
var r *Record
|
||||||
var err error
|
var err error
|
||||||
|
|||||||
@@ -75,14 +75,14 @@ func ListRules(c *gin.Context) {
|
|||||||
res []Rule
|
res []Rule
|
||||||
count int64
|
count int64
|
||||||
order = c.Query("order")
|
order = c.Query("order")
|
||||||
pageSize int
|
pageSize = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Query("pageSize") == "" {
|
if c.Query("pageSize") != "" {
|
||||||
pageSize = 10
|
if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
||||||
} else if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
if n > 0 && n < 100 {
|
||||||
if n <= 0 || n > 100 {
|
pageSize = n
|
||||||
pageSize = 10
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/li4n0/revsuit/internal/database"
|
"github.com/li4n0/revsuit/internal/database"
|
||||||
"github.com/li4n0/revsuit/internal/file"
|
"github.com/li4n0/revsuit/internal/file"
|
||||||
"github.com/li4n0/revsuit/internal/qqwry"
|
"github.com/li4n0/revsuit/internal/ipinfo"
|
||||||
"github.com/li4n0/revsuit/pkg/mysql/vmysql"
|
"github.com/li4n0/revsuit/pkg/mysql/vmysql"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
@@ -130,7 +130,7 @@ func (s *Server) ConnectionClosed(c *vmysql.Conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := newRecord(_rule, flag, user, schema, clientName, clientOS, ip, qqwry.Area(ip), supportLoadLocalData, files)
|
r, err := newRecord(_rule, flag, user, schema, clientName, clientOS, ip, ipinfo.Area(ip), supportLoadLocalData, files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("MySQL record[rule_id: %s] created failed: %s", _rule.Name, err)
|
log.Warn("MySQL record[rule_id: %s] created failed: %s", _rule.Name, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -57,14 +57,14 @@ func ListRecords(c *gin.Context) {
|
|||||||
res []Record
|
res []Record
|
||||||
count int64
|
count int64
|
||||||
order = c.Query("order")
|
order = c.Query("order")
|
||||||
pageSize int
|
pageSize = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Query("pageSize") == "" {
|
if c.Query("pageSize") != "" {
|
||||||
pageSize = 10
|
if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
||||||
} else if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
if n > 0 && n < 100 {
|
||||||
if n <= 0 || n > 100 {
|
pageSize = n
|
||||||
pageSize = 10
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,14 +63,14 @@ func ListRules(c *gin.Context) {
|
|||||||
res []Rule
|
res []Rule
|
||||||
count int64
|
count int64
|
||||||
order = c.Query("order")
|
order = c.Query("order")
|
||||||
pageSize int
|
pageSize = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Query("pageSize") == "" {
|
if c.Query("pageSize") != "" {
|
||||||
pageSize = 10
|
if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
||||||
} else if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
if n > 0 && n < 100 {
|
||||||
if n <= 0 || n > 100 {
|
pageSize = n
|
||||||
pageSize = 10
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
package rhttp
|
package rhttp
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
IpHeader string
|
IpHeader string `yaml:"ip_header"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/li4n0/revsuit/internal/database"
|
"github.com/li4n0/revsuit/internal/database"
|
||||||
"github.com/li4n0/revsuit/internal/qqwry"
|
"github.com/li4n0/revsuit/internal/ipinfo"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -166,10 +166,7 @@ func (s *Server) Receive(c *gin.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
ip := strings.Split(c.Request.RemoteAddr, ":")[0]
|
||||||
ip = strings.Split(c.Request.RemoteAddr, ":")[0]
|
|
||||||
area = qqwry.Area(ip)
|
|
||||||
)
|
|
||||||
|
|
||||||
if ip1 := c.Request.Header.Get(s.IpHeader); s.IpHeader != "" && ip1 != "" {
|
if ip1 := c.Request.Header.Get(s.IpHeader); s.IpHeader != "" && ip1 != "" {
|
||||||
ip = ip1
|
ip = ip1
|
||||||
@@ -177,7 +174,7 @@ func (s *Server) Receive(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create new record
|
// create new record
|
||||||
r, err := NewRecord(_rule, flag, c.Request.Method, u, ip, area, string(raw))
|
r, err := NewRecord(_rule, flag, c.Request.Method, u, ip, ipinfo.Area(ip), string(raw))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("HTTP record[rule_id:%d] created failed :%s", _rule.ID, err)
|
log.Warn("HTTP record[rule_id:%d] created failed :%s", _rule.ID, err)
|
||||||
code, err := strconv.Atoi(compileTpl(c, _rule.ResponseStatusCode, vars))
|
code, err := strconv.Atoi(compileTpl(c, _rule.ResponseStatusCode, vars))
|
||||||
|
|||||||
@@ -50,15 +50,14 @@ func ListRecords(c *gin.Context) {
|
|||||||
res []Record
|
res []Record
|
||||||
count int64
|
count int64
|
||||||
order = c.Query("order")
|
order = c.Query("order")
|
||||||
pageSize int
|
pageSize = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Query("pageSize") == "" {
|
if c.Query("pageSize") != "" {
|
||||||
pageSize = 10
|
if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
||||||
} else if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
if n > 0 && n < 100 {
|
||||||
pageSize = n
|
pageSize = n
|
||||||
if pageSize <= 0 || pageSize > 100 {
|
}
|
||||||
pageSize = 10
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,14 +81,14 @@ func ListRules(c *gin.Context) {
|
|||||||
res []Rule
|
res []Rule
|
||||||
count int64
|
count int64
|
||||||
order = c.Query("order")
|
order = c.Query("order")
|
||||||
pageSize int
|
pageSize = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Query("pageSize") == "" {
|
if c.Query("pageSize") != "" {
|
||||||
pageSize = 10
|
if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
||||||
} else if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
if n > 0 && n < 100 {
|
||||||
if n <= 0 || n > 100 {
|
pageSize = n
|
||||||
pageSize = 10
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,14 +46,14 @@ func ListRecords(c *gin.Context) {
|
|||||||
res []Record
|
res []Record
|
||||||
count int64
|
count int64
|
||||||
order = c.Query("order")
|
order = c.Query("order")
|
||||||
pageSize int
|
pageSize = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Query("pageSize") == "" {
|
if c.Query("pageSize") != "" {
|
||||||
pageSize = 10
|
if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
||||||
} else if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
if n > 0 && n < 100 {
|
||||||
if n <= 0 || n > 100 {
|
pageSize = n
|
||||||
pageSize = 10
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/li4n0/revsuit/internal/database"
|
"github.com/li4n0/revsuit/internal/database"
|
||||||
"github.com/li4n0/revsuit/internal/qqwry"
|
"github.com/li4n0/revsuit/internal/ipinfo"
|
||||||
"github.com/li4n0/revsuit/internal/recycler"
|
"github.com/li4n0/revsuit/internal/recycler"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
@@ -58,6 +58,7 @@ func (s *Server) handleConnection(conn net.Conn) {
|
|||||||
|
|
||||||
if err := conn.SetDeadline(time.Now().Add(time.Second * 30)); err != nil {
|
if err := conn.SetDeadline(time.Now().Add(time.Second * 30)); err != nil {
|
||||||
log.Warn("RMI set connection deadline error:%v", err)
|
log.Warn("RMI set connection deadline error:%v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ip, port, _ := net.SplitHostPort(conn.RemoteAddr().String())
|
ip, port, _ := net.SplitHostPort(conn.RemoteAddr().String())
|
||||||
@@ -66,6 +67,7 @@ func (s *Server) handleConnection(conn net.Conn) {
|
|||||||
_, err := conn.Read(buf)
|
_, err := conn.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("RMI read connection error:%v", err)
|
log.Warn("RMI read connection error:%v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Contains(buf, []byte{0x4a, 0x52, 0x4d, 0x49}) {
|
if !bytes.Contains(buf, []byte{0x4a, 0x52, 0x4d, 0x49}) {
|
||||||
@@ -86,6 +88,7 @@ func (s *Server) handleConnection(conn net.Conn) {
|
|||||||
_, err = conn.Write(send)
|
_, err = conn.Write(send)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("RMI write connection error: %v", err)
|
log.Warn("RMI write connection error: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data := make([]byte, 512)
|
data := make([]byte, 512)
|
||||||
@@ -94,6 +97,7 @@ func (s *Server) handleConnection(conn net.Conn) {
|
|||||||
n, err := conn.Read(data)
|
n, err := conn.Read(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("RMI read connection error: %v", err)
|
log.Warn("RMI read connection error: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
length += n
|
length += n
|
||||||
}
|
}
|
||||||
@@ -107,7 +111,7 @@ func (s *Server) handleConnection(conn net.Conn) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
area := qqwry.Area(ip)
|
area := ipinfo.Area(ip)
|
||||||
|
|
||||||
// create new record
|
// create new record
|
||||||
r, err := NewRecord(_rule, flag, path, ip, area)
|
r, err := NewRecord(_rule, flag, path, ip, area)
|
||||||
|
|||||||
@@ -72,14 +72,14 @@ func ListRules(c *gin.Context) {
|
|||||||
res []Rule
|
res []Rule
|
||||||
count int64
|
count int64
|
||||||
order = c.Query("order")
|
order = c.Query("order")
|
||||||
pageSize int
|
pageSize = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Query("pageSize") == "" {
|
if c.Query("pageSize") != "" {
|
||||||
pageSize = 10
|
if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
||||||
} else if n, err := strconv.Atoi(c.Query("pageSize")); err == nil {
|
if n > 0 && n < 100 {
|
||||||
if n <= 0 || n > 100 {
|
pageSize = n
|
||||||
pageSize = 10
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/li4n0/revsuit/internal/ipinfo"
|
||||||
"github.com/li4n0/revsuit/pkg/dns"
|
"github.com/li4n0/revsuit/pkg/dns"
|
||||||
"github.com/li4n0/revsuit/pkg/ftp"
|
"github.com/li4n0/revsuit/pkg/ftp"
|
||||||
"github.com/li4n0/revsuit/pkg/mysql"
|
"github.com/li4n0/revsuit/pkg/mysql"
|
||||||
@@ -16,17 +17,19 @@ type noticeConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Version float64
|
Version float64
|
||||||
Addr string
|
Addr string
|
||||||
Token string
|
Token string
|
||||||
Domain string
|
Domain string
|
||||||
ExternalIP string `yaml:"external_ip"`
|
ExternalIP string `yaml:"external_ip"`
|
||||||
Database string
|
AdminPathPrefix string `yaml:"admin_path_prefix"`
|
||||||
LogLevel string `yaml:"log_level"`
|
Database string
|
||||||
Notice noticeConfig
|
LogLevel string `yaml:"log_level"`
|
||||||
rhttp.Config
|
IpLocationDatabase ipinfo.Config `yaml:"ip_location_database"`
|
||||||
DNS dns.Config
|
Notice noticeConfig
|
||||||
MySQL mysql.Config
|
HTTP rhttp.Config
|
||||||
RMI rmi.Config
|
DNS dns.Config
|
||||||
FTP ftp.Config
|
MySQL mysql.Config
|
||||||
|
RMI rmi.Config
|
||||||
|
FTP ftp.Config
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import (
|
|||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func auth(c *gin.Context) {
|
func (revsuit *Revsuit) auth(c *gin.Context) {
|
||||||
c.SetSameSite(http.SameSiteLaxMode)
|
c.SetSameSite(http.SameSiteLaxMode)
|
||||||
c.SetCookie("token", c.Request.Header["Token"][0], 0, "/revsuit/api/", "", false, true)
|
c.SetCookie("token", c.Request.Header["Token"][0], 0, revsuit.config.AdminPathPrefix, "", false, true)
|
||||||
c.String(200, "pong")
|
c.String(200, "pong")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/li4n0/revsuit/frontend"
|
"github.com/li4n0/revsuit/frontend"
|
||||||
@@ -28,7 +29,7 @@ func (revsuit *Revsuit) registerRouter() {
|
|||||||
|
|
||||||
func (revsuit *Revsuit) registerPlatformRouter() {
|
func (revsuit *Revsuit) registerPlatformRouter() {
|
||||||
// /api need Authorization
|
// /api need Authorization
|
||||||
api := revsuit.http.Router.Group("/revsuit/api")
|
api := revsuit.http.Router.Group(revsuit.config.AdminPathPrefix + "/api")
|
||||||
api.Use(func(c *gin.Context) {
|
api.Use(func(c *gin.Context) {
|
||||||
cookieToken, err := c.Request.Cookie("token")
|
cookieToken, err := c.Request.Cookie("token")
|
||||||
if !(c.Request.Header.Get("Token") == revsuit.http.Token || err == nil && cookieToken.Value == revsuit.http.Token) {
|
if !(c.Request.Header.Get("Token") == revsuit.http.Token || err == nil && cookieToken.Value == revsuit.http.Token) {
|
||||||
@@ -39,7 +40,7 @@ func (revsuit *Revsuit) registerPlatformRouter() {
|
|||||||
revsuit.http.ApiGroup = api
|
revsuit.http.ApiGroup = api
|
||||||
|
|
||||||
//platform routers
|
//platform routers
|
||||||
api.GET("/auth", auth)
|
api.GET("/auth", revsuit.auth)
|
||||||
api.GET("/events", revsuit.events)
|
api.GET("/events", revsuit.events)
|
||||||
api.GET("/ping", ping)
|
api.GET("/ping", ping)
|
||||||
api.GET("/version", version)
|
api.GET("/version", version)
|
||||||
@@ -53,7 +54,7 @@ func (revsuit *Revsuit) registerHttpRouter() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to sub path `dist`: %v", err)
|
log.Fatal("Failed to sub path `dist`: %v", err)
|
||||||
}
|
}
|
||||||
revsuit.http.Router.StaticFS("/revsuit/admin", http.FS(fe))
|
revsuit.http.Router.StaticFS(path.Clean(revsuit.config.AdminPathPrefix+"/admin"), http.FS(fe))
|
||||||
|
|
||||||
// init settings router group
|
// init settings router group
|
||||||
settingsGroup := revsuit.http.ApiGroup.Group("setting")
|
settingsGroup := revsuit.http.ApiGroup.Group("setting")
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/li4n0/revsuit/internal/database"
|
"github.com/li4n0/revsuit/internal/database"
|
||||||
"github.com/li4n0/revsuit/internal/file"
|
"github.com/li4n0/revsuit/internal/file"
|
||||||
|
"github.com/li4n0/revsuit/internal/ipinfo"
|
||||||
"github.com/li4n0/revsuit/internal/notice"
|
"github.com/li4n0/revsuit/internal/notice"
|
||||||
"github.com/li4n0/revsuit/internal/record"
|
"github.com/li4n0/revsuit/internal/record"
|
||||||
"github.com/li4n0/revsuit/pkg/dns"
|
"github.com/li4n0/revsuit/pkg/dns"
|
||||||
@@ -17,7 +18,7 @@ import (
|
|||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const VERSION = "0.1.3-beta"
|
const VERSION = "0.1.5-beta"
|
||||||
|
|
||||||
type Revsuit struct {
|
type Revsuit struct {
|
||||||
config *Config
|
config *Config
|
||||||
@@ -178,6 +179,7 @@ func New(c *Config) *Revsuit {
|
|||||||
|
|
||||||
initDatabase(c.Database)
|
initDatabase(c.Database)
|
||||||
logLevel := initLog(c.LogLevel)
|
logLevel := initLog(c.LogLevel)
|
||||||
|
ipinfo.Init(c.IpLocationDatabase)
|
||||||
initNotice(c.Notice)
|
initNotice(c.Notice)
|
||||||
|
|
||||||
s := &Revsuit{
|
s := &Revsuit{
|
||||||
@@ -204,8 +206,8 @@ func New(c *Config) *Revsuit {
|
|||||||
if c.Token != "" {
|
if c.Token != "" {
|
||||||
s.http.SetToken(c.Token)
|
s.http.SetToken(c.Token)
|
||||||
}
|
}
|
||||||
if c.IpHeader != "" {
|
if c.HTTP.IpHeader != "" {
|
||||||
s.http.SetIpHeader(c.IpHeader)
|
s.http.SetIpHeader(c.HTTP.IpHeader)
|
||||||
}
|
}
|
||||||
if c.Domain != "" {
|
if c.Domain != "" {
|
||||||
s.dns.SetServerDomain(c.Domain)
|
s.dns.SetServerDomain(c.Domain)
|
||||||
|
|||||||
@@ -153,10 +153,11 @@ func (revsuit *Revsuit) getPlatformConfig(c *gin.Context) {
|
|||||||
res["Addr"] = revsuit.config.Addr
|
res["Addr"] = revsuit.config.Addr
|
||||||
res["Token"] = revsuit.config.Token
|
res["Token"] = revsuit.config.Token
|
||||||
res["Domain"] = revsuit.config.Domain
|
res["Domain"] = revsuit.config.Domain
|
||||||
|
res["AdminPathPrefix"] = revsuit.config.AdminPathPrefix
|
||||||
res["ExternalIP"] = revsuit.config.ExternalIP
|
res["ExternalIP"] = revsuit.config.ExternalIP
|
||||||
res["Database"] = revsuit.config.Database
|
res["Database"] = revsuit.config.Database
|
||||||
res["LogLevel"] = revsuit.config.LogLevel
|
res["LogLevel"] = revsuit.config.LogLevel
|
||||||
res["IpHeader"] = revsuit.config.IpHeader
|
res["IpHeader"] = revsuit.config.HTTP.IpHeader
|
||||||
|
|
||||||
c.JSON(200, res)
|
c.JSON(200, res)
|
||||||
}
|
}
|
||||||
@@ -194,8 +195,8 @@ func (revsuit *Revsuit) updatePlatformConfig(c *gin.Context) {
|
|||||||
log.Info("Update platform config [database] to %s", form["Database"])
|
log.Info("Update platform config [database] to %s", form["Database"])
|
||||||
}
|
}
|
||||||
|
|
||||||
if form["IpHeader"] != revsuit.config.IpHeader {
|
if form["IpHeader"] != revsuit.config.HTTP.IpHeader {
|
||||||
revsuit.config.IpHeader = form["IpHeader"]
|
revsuit.config.HTTP.IpHeader = form["IpHeader"]
|
||||||
revsuit.http.SetIpHeader(form["IpHeader"])
|
revsuit.http.SetIpHeader(form["IpHeader"])
|
||||||
log.Info("Update http config [ip_header] to %s", form["IpHeader"])
|
log.Info("Update http config [ip_header] to %s", form["IpHeader"])
|
||||||
}
|
}
|
||||||
|
|||||||