Add: external controller
This commit is contained in:
parent
f584173b11
commit
002c782051
5 changed files with 120 additions and 1 deletions
|
@ -28,12 +28,16 @@ Unfortunately, there is no native elegant way to implement golang's daemon.
|
||||||
|
|
||||||
So we can use third-party daemon tools like pm2, supervisor, and so on.
|
So we can use third-party daemon tools like pm2, supervisor, and so on.
|
||||||
|
|
||||||
In the case of pm2, we can start the daemon this way:
|
In the case of [pm2](https://github.com/Unitech/pm2), we can start the daemon this way:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pm2 start clash
|
pm2 start clash
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you have Docker installed, you can run clash directly using `docker-compose`.
|
||||||
|
|
||||||
|
[Run clash in docker](https://github.com/Dreamacro/clash/wiki/Run-clash-in-docker)
|
||||||
|
|
||||||
## Config
|
## Config
|
||||||
|
|
||||||
Configuration file at `$HOME/.config/clash/config.ini`
|
Configuration file at `$HOME/.config/clash/config.ini`
|
||||||
|
@ -45,6 +49,9 @@ Below is a simple demo configuration file:
|
||||||
port = 7890
|
port = 7890
|
||||||
socks-port = 7891
|
socks-port = 7891
|
||||||
|
|
||||||
|
# A RESTful API for clash
|
||||||
|
external-controller = 127.0.0.1:8080
|
||||||
|
|
||||||
[Proxy]
|
[Proxy]
|
||||||
# name = ss, server, port, cipher, password
|
# name = ss, server, port, cipher, password
|
||||||
# The types of cipher are consistent with go-shadowsocks2
|
# The types of cipher are consistent with go-shadowsocks2
|
||||||
|
|
83
hub/server.go
Normal file
83
hub/server.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package hub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/tunnel"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi"
|
||||||
|
"github.com/go-chi/render"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
tun = tunnel.GetInstance()
|
||||||
|
)
|
||||||
|
|
||||||
|
type Traffic struct {
|
||||||
|
Up int64 `json:"up"`
|
||||||
|
Down int64 `json:"down"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Log struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
Error string `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHub(addr string) {
|
||||||
|
r := chi.NewRouter()
|
||||||
|
|
||||||
|
r.Get("/traffic", traffic)
|
||||||
|
r.Get("/logs", getLogs)
|
||||||
|
|
||||||
|
err := http.ListenAndServe(addr, r)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("External controller error: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traffic(w http.ResponseWriter, r *http.Request) {
|
||||||
|
render.Status(r, http.StatusOK)
|
||||||
|
|
||||||
|
tick := time.NewTicker(time.Second)
|
||||||
|
t := tun.Traffic()
|
||||||
|
for range tick.C {
|
||||||
|
up, down := t.Now()
|
||||||
|
if err := json.NewEncoder(w).Encode(Traffic{
|
||||||
|
Up: up,
|
||||||
|
Down: down,
|
||||||
|
}); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
w.(http.Flusher).Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLogs(w http.ResponseWriter, r *http.Request) {
|
||||||
|
src := tun.Log()
|
||||||
|
sub, err := src.Subscribe()
|
||||||
|
defer src.UnSubscribe(sub)
|
||||||
|
if err != nil {
|
||||||
|
render.Status(r, http.StatusInternalServerError)
|
||||||
|
render.JSON(w, r, Error{
|
||||||
|
Error: err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
render.Status(r, http.StatusOK)
|
||||||
|
for elm := range sub {
|
||||||
|
log := elm.(tunnel.Log)
|
||||||
|
if err := json.NewEncoder(w).Encode(Log{
|
||||||
|
Type: log.Type(),
|
||||||
|
Payload: log.Payload,
|
||||||
|
}); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
w.(http.Flusher).Flush()
|
||||||
|
}
|
||||||
|
}
|
6
main.go
6
main.go
|
@ -6,6 +6,7 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
"github.com/Dreamacro/clash/hub"
|
||||||
"github.com/Dreamacro/clash/proxy/http"
|
"github.com/Dreamacro/clash/proxy/http"
|
||||||
"github.com/Dreamacro/clash/proxy/socks"
|
"github.com/Dreamacro/clash/proxy/socks"
|
||||||
"github.com/Dreamacro/clash/tunnel"
|
"github.com/Dreamacro/clash/tunnel"
|
||||||
|
@ -37,6 +38,11 @@ func main() {
|
||||||
go http.NewHttpProxy(port)
|
go http.NewHttpProxy(port)
|
||||||
go socks.NewSocksProxy(socksPort)
|
go socks.NewSocksProxy(socksPort)
|
||||||
|
|
||||||
|
// Hub
|
||||||
|
if key, err := section.GetKey("external-controller"); err == nil {
|
||||||
|
go hub.NewHub(key.Value())
|
||||||
|
}
|
||||||
|
|
||||||
sigCh := make(chan os.Signal, 1)
|
sigCh := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
||||||
<-sigCh
|
<-sigCh
|
||||||
|
|
|
@ -20,6 +20,21 @@ type Log struct {
|
||||||
Payload string
|
Payload string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *Log) Type() string {
|
||||||
|
switch l.LogType {
|
||||||
|
case INFO:
|
||||||
|
return "Info"
|
||||||
|
case WARNING:
|
||||||
|
return "Warning"
|
||||||
|
case ERROR:
|
||||||
|
return "Error"
|
||||||
|
case DEBUG:
|
||||||
|
return "Debug"
|
||||||
|
default:
|
||||||
|
return "Unknow"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func print(data Log) {
|
func print(data Log) {
|
||||||
switch data.LogType {
|
switch data.LogType {
|
||||||
case INFO:
|
case INFO:
|
||||||
|
|
|
@ -34,6 +34,14 @@ func (t *Tunnel) Add(req C.ServerAdapter) {
|
||||||
t.queue.In() <- req
|
t.queue.In() <- req
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tunnel) Traffic() *C.Traffic {
|
||||||
|
return t.traffic
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tunnel) Log() *observable.Observable {
|
||||||
|
return t.observable
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tunnel) UpdateConfig() (err error) {
|
func (t *Tunnel) UpdateConfig() (err error) {
|
||||||
cfg, err := C.GetConfig()
|
cfg, err := C.GetConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue