diff --git a/Management/management.go b/Management/management.go index a99c7e6..c001ba9 100644 --- a/Management/management.go +++ b/Management/management.go @@ -9,16 +9,17 @@ import ( "time" + "domains" + "github.com/asaskevich/govalidator" - domains "github.com/cr3a70r/shield/Domains" ) var Settings T_Management type T_Management struct { - Users []T_User `json:"Users"` - Domains domains.T_Domains `json:"Names"` - Debug bool `json:"Debug"` + Users []T_User `json:"Users"` + Domains []domains.T_Domain `json:"Names"` + Debug bool `json:"Debug"` } type T_User struct { @@ -28,8 +29,29 @@ type T_User struct { CreatedDate string `json:"CreatedDate"` } -func (T_Management) SaveConfig() { +func (T_Management) SaveConfig() error { + configFile, err := os.OpenFile("config.json", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755) + + if err == nil { + configByte, err := json.MarshalIndent(Settings, "", " ") + if err != nil { + log.Fatal("management.SaveConfig: could not Marshall Settings: ", err) + return errors.New("management.SaveConfig: could not Marshall Settings: " + err.Error()) + } + _, err = configFile.Write(configByte) + if err != nil { + log.Fatal("management.SaveConfig: could not Write Settings: ", err) + return errors.New("management.SaveConfig: could not Write Settings: " + err.Error()) + } + } else { + log.Fatal("management.SaveConfig: could not create new config.json file: ", err) + return errors.New("management.SaveConfig: could not create new config.json file: " + err.Error()) + } + + defer configFile.Close() + + return nil } func (T_Management) LoadConfig() { @@ -149,15 +171,11 @@ func (T_Management) OnboardDomain(name string, realServer string, realPort strin return false, errors.New("given realPort is not a valid Port number") } - domains.Names.AddByParams(name, realServer, realPort) + Settings.AddDomainByParams(name, realServer, realPort) return true, nil } -func (T_Management) RemoveDomain(name string) { - domains.Names.RemoveDomain(name) -} - func (T_Management) UserFindByEmail(email string) (T_User, error) { found := false var temp T_User @@ -190,3 +208,40 @@ func (T_Management) ToString() string { return string(managementString) } + +//--- Domains +func (T_Management) AddDomainByDomain(domain domains.T_Domain) { + domain.Status = domains.Onboarding + Settings.Domains = append(Settings.Domains, domain) +} + +func (T_Management) AddDomainByParams(name string, realServer string, realPort string) { + var temp domains.T_Domain + temp.DomainName = name + temp.RealServer = realServer + temp.RealPort = realPort + temp.Status = domains.Onboarding + + Settings.AddDomainByDomain(temp) +} + +func (T_Management) RemoveDomain(name string) { + for index, v := range Settings.Domains { + if v.DomainName == name { + temp := append(Settings.Domains[:index], Settings.Domains[index+1]) + Settings.Domains = temp + } + } +} + +func (T_Management) FindDomainByName(name string) domains.T_Domain { + var temp domains.T_Domain + for index, v := range Settings.Domains { + if v.DomainName == name { + temp = Settings.Domains[index] + } + } + return temp +} + +//--- END Domains diff --git a/Management/memento.go b/Management/memento.go index 9758213..d25896c 100644 --- a/Management/memento.go +++ b/Management/memento.go @@ -1,4 +1,11 @@ package management // Originator is T_Management - + +type Memento struct { + State T_Management +} + +func (e *T_Management) CreateMemento() *Memento { + return &Memento{State: *e} +} diff --git a/Management/webserver.go b/Management/webserver.go index 9a0161e..57d315d 100644 --- a/Management/webserver.go +++ b/Management/webserver.go @@ -1,9 +1,12 @@ package management import ( + "bytes" + "domains" "encoding/json" "log" "net/http" + "os" "path/filepath" "text/template" @@ -23,9 +26,16 @@ func StartWebserver(addr string) { router.HandleFunc("/", renderIndex) router.HandleFunc("/config", config) router.HandleFunc("/dashboard", dashboard) - router.HandleFunc("/protection", protection) + router.HandleFunc("/routing", routing) + router.HandleFunc("/acls", acls) + router.HandleFunc("/domains", view_domains) + router.HandleFunc("/domain/{id}", view_domain) + router.HandleFunc("/config", config) + router.HandleFunc("/api/domains", api_domains) + router.HandleFunc("/api/domain/{id}", api_domain) + log.Fatal(http.ListenAndServe(addr, router)) } @@ -99,9 +109,39 @@ func dashboard(w http.ResponseWriter, r *http.Request) { } } -func protection(w http.ResponseWriter, r *http.Request) { +func routing(w http.ResponseWriter, r *http.Request) { + fpTemplate := filepath.Join("static", "template.html") + fpPage := filepath.Join("static", "routing.html") + + tmpl, err := template.ParseFiles(fpPage, fpTemplate) + if err != nil { + log.Println("webserver.protection: " + err.Error()) + } + + err = tmpl.ExecuteTemplate(w, "template.html", nil) + if err != nil { + log.Println("webserver.protection: " + err.Error()) + } +} + +func acls(w http.ResponseWriter, r *http.Request) { + fpTemplate := filepath.Join("static", "template.html") + fpPage := filepath.Join("static", "acls.html") + + tmpl, err := template.ParseFiles(fpPage, fpTemplate) + if err != nil { + log.Println("webserver.protection: " + err.Error()) + } + + err = tmpl.ExecuteTemplate(w, "template.html", nil) + if err != nil { + log.Println("webserver.protection: " + err.Error()) + } +} + +func view_domains(w http.ResponseWriter, r *http.Request) { fpTemplate := filepath.Join("static", "template.html") - fpPage := filepath.Join("static", "protection.html") + fpPage := filepath.Join("static", "domains.html") tmpl, err := template.ParseFiles(fpPage, fpTemplate) if err != nil { @@ -114,8 +154,34 @@ func protection(w http.ResponseWriter, r *http.Request) { } } +type ViewDomains struct { + Domain domains.T_Domain +} + +func view_domain(w http.ResponseWriter, r *http.Request) { + fpTemplate := filepath.Join("static", "template.html") + fpPage := filepath.Join("static", "domain.html") + + httpVars := mux.Vars(r) + id := httpVars["id"] + + var view ViewDomains + view.Domain = Settings.FindDomainByName(id) + + tmpl, err := template.ParseFiles(fpPage, fpTemplate) + if err != nil { + log.Println("webserver.protection: " + err.Error()) + } + + err = tmpl.ExecuteTemplate(w, "template.html", view) + if err != nil { + log.Println("webserver.protection: " + err.Error()) + } +} + type View struct { - Data string + Data string + Config string } func config(w http.ResponseWriter, r *http.Request) { @@ -127,10 +193,22 @@ func config(w http.ResponseWriter, r *http.Request) { log.Println("webserver.config: " + err.Error()) } - bt, err := json.MarshalIndent(Settings, "", " ") - vd := View{string(bt)} + logFile, err := os.Open("runlog.log") + if err != nil { + log.Fatal(err) + } else { + log.SetOutput(logFile) + } + buf := new(bytes.Buffer) + buf.ReadFrom(logFile) - //vd := ViewData{&Settings} + defer logFile.Close() + + bt, err := json.MarshalIndent(Settings, "", " ") + if err != nil { + log.Println("webserver.config: " + err.Error()) + } + vd := View{string(bt), buf.String()} err = tmpl.ExecuteTemplate(w, "template.html", vd) if err != nil { @@ -149,3 +227,44 @@ func requireAuth(h http.Handler) http.Handler { h.ServeHTTP(w, r) }) } + +func api_domains(w http.ResponseWriter, r *http.Request) { + if r.Method == "GET" { + Utils.RespondJSON(Settings.Domains, http.StatusOK, w) + } + if r.Method == "POST" { + var msgJSON Utils.Msg + var req domains.T_Domain + err := json.NewDecoder(r.Body).Decode(&req) + if err != nil { + log.Println("webserver.api_domains: " + err.Error()) + + msgJSON.Msg = err.Error() + Utils.RespondJSON(msgJSON, http.StatusBadRequest, w) + } + + Settings.AddDomainByDomain(req) + + err = Settings.SaveConfig() + if err != nil { + log.Println("webserver.api_domains: " + err.Error()) + + msgJSON.Msg = err.Error() + Utils.RespondJSON(msgJSON, http.StatusBadRequest, w) + } + + msgJSON.Msg = "OK" + Utils.RespondJSON(msgJSON, http.StatusOK, w) + + } +} + +func api_domain(w http.ResponseWriter, r *http.Request) { + httpVars := mux.Vars(r) + id := httpVars["id"] + + var msgJSON Utils.Msg + msgJSON.Msg = id + + Utils.RespondJSON(msgJSON, http.StatusBadRequest, w) +} diff --git a/Proxy/proxy.go b/Proxy/proxy.go new file mode 100644 index 0000000..6ba5724 --- /dev/null +++ b/Proxy/proxy.go @@ -0,0 +1,93 @@ +package proxy + +import ( + "bytes" + "context" + "fmt" + "io/ioutil" + "net/http" + "net/http/httputil" + "net/url" + + logger "github.com/cr3a70r/shield/Utils" +) + +type ProxyHttpServer struct { + ctx context.Context + http.Server + AddressAndPort string + Name string + logger *logger.Logger +} + +type ReverseProxy struct { + url *url.URL + proxy *httputil.ReverseProxy + logger *logger.Logger + port string +} + +type Override struct { + Header string + Match string + Host string + Path string +} + +type Config struct { + Path string + Host string + Override Override +} + +func NewProxy(urlString string, transport http.RoundTripper, director *httputil.ReverseProxy, logger *logger.Logger, port string) *ReverseProxy { + providedUrl, err := url.Parse(urlString) + + if err != nil { + return nil + } + + p := httputil.NewSingleHostReverseProxy(providedUrl) + p.Transport = transport + p.Director = director.Director + p.ModifyResponse = UpdateResponse + + return &ReverseProxy{ + url: providedUrl, + proxy: p, + logger: logger, + port: port, + } +} + +func (p *ReverseProxy) Handler(w http.ResponseWriter, r *http.Request) { + p.logger.PrintInfo("", map[string]string{ + "accept": r.Header.Get("Accept"), + "accept-encoding": r.Header.Get("Accept-Encoding"), + "accept-language": r.Header.Get("Accept-Language"), + "cache-control": r.Header.Get("Cache-Control"), + "connection": r.Header.Get("Connection"), + "pragma": r.Header.Get("Pragma"), + "sec-ch-ua": r.Header.Get("Sec-Ch-Ua"), + "user-agent": r.Header.Get("User-Agent"), + }) + + xsCode := r.Header.Get("X-Code") + + if r.Header.Get(xsCode) != "" { + p.logger.PrintInfo("", map[string]string{ + "xsCode": xsCode, + }) + } + + p.proxy.ServeHTTP(w, r) +} + +func UpdateResponse(r *http.Response) error { + + buf := bytes.NewBufferString("") + + r.Body = ioutil.NopCloser(buf) + r.Header["Content-Length"] = []string{fmt.Sprint(buf.Len())} + return nil +} diff --git a/Utils/Jsonlog.go b/Utils/Jsonlog.go new file mode 100644 index 0000000..23a1a81 --- /dev/null +++ b/Utils/Jsonlog.go @@ -0,0 +1,107 @@ +package Utils + +import ( + "encoding/json" + "io" + "os" + "runtime/debug" + "sync" + "time" +) + +// Define a Level type to represent the severity level for a log entry. +type Level int8 + +// Initialize constants which represent a specific severity level. We use the iota +// keyword as a shortcut to +const ( + LevelInfo Level = iota + LevelError + LevelFatal + LevelOff +) + +// assign successive integer values to the constants. +// Has the value 0. // Has the value 1. // Has the value 2. // Has the value 3. +// Return a human-friendly string for the severity level. +func (l Level) String() string { + switch l { + case LevelInfo: + return "INFO" + case LevelError: + return "ERROR" + case LevelFatal: + return "FATAL" + default: + return "" + } +} + +// Define a custom Logger type. This holds the output destination that the log entries // will be written to, the minimum severity level that log entries will be written for, // plus a mutex for coordinating the writes. +type Logger struct { + out io.Writer + minLevel Level + mu sync.Mutex +} + +// Return a new Logger instance which writes log entries at or above a minimum severity // level to a specific output destination. +func New(out io.Writer, minLevel Level) *Logger { + return &Logger{out: out, + minLevel: minLevel} +} + +// Declare some helper methods for writing log entries at the different levels. Notice // that these all accept a map as the second parameter which can contain any arbitrary // 'properties' that you want to appear in the log entry. +func (l *Logger) PrintInfo(message string, properties map[string]string) { + l.print(LevelInfo, message, properties) +} +func (l *Logger) PrintError(err error, properties map[string]string) { + l.print(LevelError, err.Error(), properties) +} +func (l *Logger) PrintFatal(err error, properties map[string]string) { + l.print(LevelFatal, err.Error(), properties) + os.Exit(1) // For entries at the FATAL level, we also terminate the application. +} + +// Print is an internal method for writing the log entry. +func (l *Logger) print(level Level, message string, properties map[string]string) (int, error) { // If the severity level of the log entry is below the minimum severity for the + // logger, then return with no further action. + if level < l.minLevel { + return 0, nil + } + // Declare an anonymous struct holding the data for the log entry. + + aux := struct { + Level string `json:"level"` + Time string `json:"time"` + Message string `json:"message"` + Properties map[string]string `json:"properties,omitempty"` + Trace string `json:"trace,omitempty"` + }{ + Level: level.String(), + Time: time.Now().UTC().Format(time.RFC3339), Message: message, + Properties: properties, + } + // Include a stack trace for entries at the ERROR and FATAL levels. + if level >= LevelError { + aux.Trace = string(debug.Stack()) + } + // Declare a line variable for holding the actual log entry text. + var line []byte + // Marshal the anonymous struct to JSON and store it in the line variable. If there // was a problem creating the JSON, set the contents of the log entry to be that + // plain-text error message instead. + line, err := json.Marshal(aux) + if err != nil { + line = []byte(LevelError.String() + ": unable to marshal log message: " + err.Error()) + } + // Lock the mutex so that no two writes to the output destination cannot happen // concurrently. If we don't do this, it's possible that the text for two or more // log entries will be intermingled in the output. + l.mu.Lock() + defer l.mu.Unlock() + // Write the log entry followed by a newline. + return l.out.Write(append(line, '\n')) +} + +// We also implement a Write() method on our Logger type so that it satisfies the +// io.Writer interface. This writes a log entry at the ERROR level with no additional // properties. +func (l *Logger) Write(message []byte) (n int, err error) { + return l.print(LevelError, string(message), nil) +} diff --git a/Utils/Utils.go b/Utils/Utils.go index a250baf..0034a67 100644 --- a/Utils/Utils.go +++ b/Utils/Utils.go @@ -5,6 +5,10 @@ import ( "net/http" ) +type Msg struct { + Msg string +} + func RespondJSON(data interface{}, code int, writer http.ResponseWriter) { writer.Header().Add("Content-type", "application/json") writer.WriteHeader(code) diff --git a/shield b/shield index 2e1c913..a518629 100755 Binary files a/shield and b/shield differ diff --git a/shield.go b/shield.go index 80fcd9a..c7d7ff9 100644 --- a/shield.go +++ b/shield.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "log" "os" @@ -14,10 +15,30 @@ func main() { } else { log.SetOutput(logFile) } - defer logFile.Close() + /* + proxyLog, err := os.OpenFile("proxy.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + log.Fatal(err) + } + + defer proxyLog.Close() + + + //proxy + transport := &http.Transport{ + DialContext: (&net.Dialer{ + Timeout: 5 * time.Second, + }).DialContext, + } + */ + management.Settings.Initialize() management.StartWebserver("0.0.0.0:8080") } + +func cleanup() { + fmt.Println("Closing Application") +} diff --git a/static/acls.html b/static/acls.html new file mode 100755 index 0000000..47b84d4 --- /dev/null +++ b/static/acls.html @@ -0,0 +1,270 @@ + +{{define "title"}} +Protection | Shield +{{end}} + +{{define "body"}} + +
+
+
+ Prefix + + +
+
+ -Iface + + + +
+
+ + + +
+ +
+
+
+ + +
+
+ + +
+
+
+ + + + + +{{ .Data }} + +{{end}} \ No newline at end of file diff --git a/static/config.html b/static/config.html old mode 100644 new mode 100755 index c502676..fc806ad --- a/static/config.html +++ b/static/config.html @@ -4,10 +4,15 @@ Config | Shield {{define "body"}} -
- - -
- +
+
+ + +
+
+ + +
+
{{end}} \ No newline at end of file diff --git a/static/dashboard.html b/static/dashboard.html old mode 100644 new mode 100755 index 2f97624..f6c8923 --- a/static/dashboard.html +++ b/static/dashboard.html @@ -4,7 +4,26 @@ Dashboard | Shield {{end}} {{define "body"}} -

Hi

-dskflsjflksdjfls -dflsdfsdlfks -{{end}} \ No newline at end of file + +
+
+ Routing +
+
+ ACLs +
+
+ + + + + +{{end}} + + + diff --git a/static/domain.html b/static/domain.html new file mode 100755 index 0000000..69328ae --- /dev/null +++ b/static/domain.html @@ -0,0 +1,114 @@ + +{{define "title"}} +Protection | Shield +{{end}} + +{{define "body"}} + + + + + + + + + + + + + + + + + + +
DomainServerPortStop Lists
{{ .Domain.DomainName}}{{ .Domain.RealServer}}{{ .Domain.RealPort}} + +
+ +
+
+
+ TEST 1 +
+
+ TEST 2 +
+
+ TEST - 3 +
+ +
+ +
+ + + +{{ .Data }} + +{{end}} \ No newline at end of file diff --git a/static/domains.html b/static/domains.html new file mode 100755 index 0000000..ff9df3c --- /dev/null +++ b/static/domains.html @@ -0,0 +1,137 @@ + +{{define "title"}} +Protection | Shield +{{end}} + +{{define "body"}} + + + + + + + + + + + + + + + + + + +
DomainServerPortAction
1@domainname@server@port
+ +
+
+
+ TEST - 1 +
+
+ TEST - 2 +
+
+ TEST - 3 +
+ +
+
+
+ +
+
+
+ + + + + + +{{ .Data }} + +{{end}} \ No newline at end of file diff --git a/static/index.html b/static/index.html old mode 100644 new mode 100755 diff --git a/static/protection.html b/static/protection.html deleted file mode 100644 index bc96572..0000000 --- a/static/protection.html +++ /dev/null @@ -1,30 +0,0 @@ - -{{define "title"}} -Protection | Shield -{{end}} - -{{define "body"}} - - - - - - - - - - - - - - - - - - - - - - -
DomainReal ServerReal PortStatusAction
Test8.8.8.880OnboardingEditDelete
-{{end}} \ No newline at end of file diff --git a/static/routericon.png b/static/routericon.png new file mode 100644 index 0000000..19f7b8e Binary files /dev/null and b/static/routericon.png differ diff --git a/static/routing.html b/static/routing.html new file mode 100755 index 0000000..47b84d4 --- /dev/null +++ b/static/routing.html @@ -0,0 +1,270 @@ + +{{define "title"}} +Protection | Shield +{{end}} + +{{define "body"}} + +
+
+
+ Prefix + + +
+
+ -Iface + + + +
+
+ + + +
+ +
+
+
+ + +
+
+ + +
+
+
+ + + + + +{{ .Data }} + +{{end}} \ No newline at end of file diff --git a/static/template.html b/static/template.html old mode 100644 new mode 100755 index 6114232..8b3d330 --- a/static/template.html +++ b/static/template.html @@ -6,12 +6,16 @@ - + {{ template "title"}} - + +