Skip to content

Commit

Permalink
feat: reload rule by manager
Browse files Browse the repository at this point in the history
  • Loading branch information
xjdrew committed Dec 26, 2023
1 parent a0dd483 commit 754c81e
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 285 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 2023/12/26
- [x] feat: upgrade to surge like config
- [x] feat: support windows 10
- [x] tech: merge proxy code
- [x] feat: reload rule by manager: curl http://127.0.0.1:9200/reload

# plan
- [ ] feat: default hijack dns query
- [ ] feat: show process name of network
- [ ] bug: traffic will be endless loop if proxy's ip use proxy by rule
- [ ] feat: support ss protocol
- [ ] feat: support IPv6
- [ ] feat: update GEOIP database
13 changes: 3 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,9 @@ The default web status port is 9200 , just visit http://localhost:9200/ to check
<img src=./misc/images/kone_webui.png border=0>

## Documents
* [how to use with Raspberry Pi (在树莓派上使用kone)](./misc/docs/how-to-use-with-raspberry-pi.md)
* [how to use kone in an ENT network (企业网中如何使用kone)](./misc/docs/kone-in-ent-network.md)
* [how to make gotunnel & kone work together(gotunnel和kone的珠联璧合)](./misc/docs/gotunnel-kone-work-together.md)
* [how to use with Raspberry Pi](./misc/docs/how-to-use-with-raspberry-pi.md)
* [how to use kone in an ENT network](./misc/docs/kone-in-ent-network.md)
* [how to make gotunnel & kone work together](./misc/docs/gotunnel-kone-work-together.md)

## License
The MIT License (MIT) Copyright (c) 2016 xjdrew

## todo
- [x] upgrade to surge like config
- [x] support windows 10
- [ ] merge proxy code
- [ ] default hijack dns query
- [ ] show process name of network
19 changes: 8 additions & 11 deletions cmd/kone/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,11 @@ var VERSION = "0.3-dev"

var logger = logging.MustGetLogger("kone")

func InitLogger(debug bool) {
format := logging.MustStringFormatter(
func init() {
logging.SetFormatter(logging.MustStringFormatter(
`%{color}%{time:06-01-02 15:04:05.000} %{level:.4s} @%{shortfile}%{color:reset} %{message}`,
)
logging.SetFormatter(format)
))
logging.SetBackend(logging.NewLogBackend(os.Stdout, "", 0))

if debug {
logging.SetLevel(logging.DEBUG, "kone")
} else {
logging.SetLevel(logging.INFO, "kone")
}
}

func main() {
Expand All @@ -43,7 +36,11 @@ func main() {
os.Exit(1)
}

InitLogger(*debug)
if *debug {
logging.SetLevel(logging.DEBUG, "kone")
} else {
logging.SetLevel(logging.INFO, "kone")
}

configFile := *config
if configFile == "" {
Expand Down
13 changes: 11 additions & 2 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import (
"gopkg.in/ini.v1"
)

func init() {
ini.PrettyFormat = true
}

const (
HTTP_PROXY = "http_proxy"
HTTPS_PROXY = "https_proxy"
Expand Down Expand Up @@ -48,6 +52,9 @@ type RuleConfig struct {
}

type KoneConfig struct {
source interface{} // config source: file name or raw ini data
inif *ini.File // parsed ini file

General GeneralConfig
Core CoreConfig
Proxy map[string]string
Expand Down Expand Up @@ -87,8 +94,9 @@ func (cfg *KoneConfig) check() (err error) {
return nil
}

func ParseConfig(filename interface{}) (*KoneConfig, error) {
func ParseConfig(source interface{}) (*KoneConfig, error) {
cfg := new(KoneConfig)
cfg.source = source

// set default value
cfg.Core.Network = "10.192.0.1/16"
Expand All @@ -107,11 +115,12 @@ func ParseConfig(filename interface{}) (*KoneConfig, error) {
cfg.Core.DnsWriteTimeout = DnsDefaultWriteTimeout

// decode config value
f, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true, KeyValueDelimiters: "="}, filename)
f, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true, KeyValueDelimiters: "="}, source)
if err != nil {
logger.Errorf("%v", err)
return nil, err
}
cfg.inif = f

err = f.MapTo(cfg)
if err != nil {
Expand Down
13 changes: 12 additions & 1 deletion dns_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,21 @@ func (c *DnsTable) clearExpiredNonProxyDomain(now time.Time) {
for domain, expired := range c.nonProxyDomains {
if expired.Before(now) {
delete(c.nonProxyDomains, domain)
logger.Debugf("[dns] release non proxy domain: %s", domain)
logger.Debugf("[dns] release expired non proxy domain: %s", domain)
}
}
}

func (c *DnsTable) ClearNonProxyDomain() {
c.npdLock.Lock()
defer c.npdLock.Unlock()
for domain := range c.nonProxyDomains {
delete(c.nonProxyDomains, domain)
logger.Debugf("[dns] release non proxy domain: %s", domain)

}
}

func (c *DnsTable) clearExpiredDomain(now time.Time) {
c.recordsLock.Lock()
defer c.recordsLock.Unlock()
Expand Down Expand Up @@ -189,6 +199,7 @@ func (c *DnsTable) Serve() error {
tick := time.NewTicker(60 * time.Second)
for now := range tick.C {
c.clearExpiredDomain(now)
//TODO: is it necessary?
c.clearExpiredNonProxyDomain(now)
}
return nil
Expand Down
58 changes: 55 additions & 3 deletions manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,24 @@ table th.title {
</table>
{{template "footer" .}}
{{end}}
{{define "config"}}
{{template "header" .}}
<h2>Config</h2>
<ul>
<li>rules: {{.RuleCount}}</li>
</ul>
<table>
<tr>
<th>Source</th>
</tr>
<tr>
<td style="text-align:left;"><pre>{{.Source}}</pre></td>
</tr>
</table>
{{template "footer" .}}
{{end}}
`

// statistical data of every connection
Expand Down Expand Up @@ -212,6 +230,7 @@ type TrafficRecord struct {

type Manager struct {
one *One
cfg *KoneConfig
startTime time.Time // process start time
listen string
tmpl *template.Template
Expand Down Expand Up @@ -255,6 +274,8 @@ func (m *Manager) indexHandle(w io.Writer, r *http.Request) error {
"/website/",
"/proxy/",
"/dns/",
"/reload/",
"/config/",
},
})
}
Expand Down Expand Up @@ -343,6 +364,34 @@ func (m *Manager) dnsHandle(w io.Writer, r *http.Request) error {
})
}

func (m *Manager) reloadHandle(w io.Writer, r *http.Request) error {
logger.Infof("[manager] reload config")
newcfg, err := ParseConfig(m.cfg.source)
if err != nil {
return err
}

err = m.one.Reload(newcfg)
if err != nil {
return err
}

m.cfg = newcfg
w.Write([]byte("reload succeed"))
return nil
}

func (m *Manager) configHandle(w io.Writer, r *http.Request) error {
b := bytes.NewBuffer([]byte{})
m.cfg.inif.WriteTo(b)

return m.tmpl.ExecuteTemplate(w, "config", map[string]interface{}{
"Title": "Config",
"RuleCount": len(m.cfg.Rule),
"Source": string(b.Bytes()),
})
}

// statistical data api
func (m *Manager) consumeData() {
accumulate := func(s map[string]*TrafficRecord, name string, endpoint string, upload int64, download int64, now time.Time) {
Expand Down Expand Up @@ -394,14 +443,16 @@ func (m *Manager) Serve() error {
http.HandleFunc("/website/", handleWrapper(m.websiteHandle))
http.HandleFunc("/proxy/", handleWrapper(m.proxyHandle))
http.HandleFunc("/dns/", handleWrapper(m.dnsHandle))
http.HandleFunc("/reload/", handleWrapper(m.reloadHandle))
http.HandleFunc("/config/", handleWrapper(m.configHandle))
go m.consumeData()

logger.Infof("[manager] listen on: %s", m.listen)
return http.ListenAndServe(m.listen, nil)
}

func NewManager(one *One, cfg GeneralConfig) *Manager {
if cfg.ManagerAddr == "" {
func NewManager(one *One, cfg *KoneConfig) *Manager {
if cfg.General.ManagerAddr == "" {
return nil
}

Expand Down Expand Up @@ -441,8 +492,9 @@ func NewManager(one *One, cfg GeneralConfig) *Manager {

return &Manager{
one: one,
cfg: cfg,
startTime: time.Now(),
listen: cfg.ManagerAddr,
listen: cfg.General.ManagerAddr,
dataCh: make(chan ConnData),
hosts: make(map[string]*TrafficRecord),
websites: make(map[string]*TrafficRecord),
Expand Down
Loading

0 comments on commit 754c81e

Please sign in to comment.