added base reverse proxy

This commit is contained in:
2024-08-22 17:14:13 +01:00
parent 9d9e385909
commit 505ef3b982
12 changed files with 221 additions and 18 deletions

135
server/ReverseProxy.go Normal file
View File

@@ -0,0 +1,135 @@
// source:https://github.com/afoley587/go-rev-proxy/tree/main
package server
import (
"errors"
"fmt"
"github.com/gin-gonic/gin"
"log"
"net/http"
"net/http/httputil"
"net/url"
)
var (
//RunPort = 2002 // The server port to run on
//ReverseServerAddr = fmt.Sprint("0.0.0.0:", RunPort) // this is our reverse server ip address
//InsideProxyHostname = fmt.Sprint("proxy:", RunPort) // Requests from private network
//OutsideProxyHostname = fmt.Sprint("registration.localhost:", RunPort) // Requests from public network
KnownAddresses = map[string]string{} // Known Addresses
)
type RegistrationRequest struct {
OutsideHost string // Outside host address. The hostname or IP on the public network. For example foo.bar.com or foo.localhost
InsideHost string // Inside host address. The hostname or IP on the internal network. For example 192.168.10.5
}
// This function checks if TLS was enabled on the request
// and translates it to the proper scheme (http or https)
func GetScheme(c *gin.Context) string {
if c.Request.TLS != nil {
return "https"
} else {
return "http"
}
}
// IsRegistrationRequest checks if an incoming request is meant to register
// a new inside/outside hostname pair by checking if the hostname and
// path match a specific combination.
// If the host is our registration.localhost or proxy hostname
// AND if the path is /register, we will register a new endpoint
//func IsRegistrationRequest(c *gin.Context) bool {
// isRR := ((c.Request.Host == InsideProxyHostname || c.Request.Host == OutsideProxyHostname) &&
// c.Request.URL.String() == "/register")
// return isRR
//}
//
//// SaveRegistrationRequest saves an inside/outside hostname pairing
//// to our KnownAddresses map so we can use it later. Effectively
//// registering a new endpoint for us
//func SaveRegistrationRequest(c *gin.Context) error {
// var rr RegistrationRequest
// log.Println(c.Request.Body)
// err := c.BindJSON(&rr)
//
// if err != nil {
// return err
// }
//
// log.Println("Registering", rr.OutsideHost, "to", rr.InsideHost)
// KnownAddresses[rr.OutsideHost] = rr.InsideHost
// return nil
//}
// SaveRegistration Creates registration of proxy node
func SaveRegistration(OutsideHost string, InsideHost string) error {
_, ok := KnownAddresses[OutsideHost]
if !ok {
return errors.New("domain name provided already exists")
}
KnownAddresses[OutsideHost] = InsideHost
return nil
}
// Proxy runs the actual proxy and will look at the
// hostnames requested from the received request. It will
// then translate that to the inside hostname and forward the
// request
func Proxy(c *gin.Context) {
// Get if HTTP or HTTPS
scheme := GetScheme(c)
log.Println(scheme, c.Request.Host, c.Request.URL.String())
// Translate the outside hostname to the inside hostname
forwardTo, ok := KnownAddresses[c.Request.Host]
if !ok {
log.Printf("Unkown Host: %v", c.Request.Host)
c.String(400, "Unkown Host")
return
}
rUrl := fmt.Sprintf("%v://%v%v", scheme, forwardTo, c.Request.URL)
remote, err := url.Parse(rUrl)
if err != nil {
log.Println(err)
c.String(500, "Error Proxying Host")
return
}
log.Println("Forwarding request to", remote)
// Forward the request to the inside remote server
// https://pkg.go.dev/net/http/httputil#NewSingleHostReverseProxy
proxy := httputil.NewSingleHostReverseProxy(remote)
// Director is a function which modifies
// the request into a new request to be sent
// https://pkg.go.dev/net/http/httputil#ReverseProxy
proxy.Director = func(req *http.Request) {
req.Header = c.Request.Header
req.Host = remote.Host
req.URL.Scheme = remote.Scheme
req.URL.Host = remote.Host
req.URL.Path = c.Param("path")
}
proxy.ServeHTTP(c.Writer, c.Request)
}
func ProxyRun(port string) {
r := gin.Default()
// all paths should be handled by Proxy()
r.Any("/*path", Proxy)
if err := r.Run(fmt.Sprint("0.0.0.0:", port)); err != nil {
log.Printf("Error: %v", err)
}
}

View File

@@ -16,9 +16,24 @@ import (
"time"
)
type ReverseProxy struct {
IPAddress string
Port string
}
// ReverseProxies Reverse to the map such as ReverseProxies[<domain nane>]ReverseProxy type
var ReverseProxies map[string]ReverseProxy
func Server() (*gin.Engine, error) {
r := gin.Default()
// "The make function allocates and initializes a hash map data
//structure and returns a map value that points to it.
//The specifics of that data structure are an implementation
//detail of the runtime and are not specified by the language itself."
// source: https://go.dev/blog/maps
ReverseProxies = make(map[string]ReverseProxy)
//Get Server port based on the config file
config, err := config.ConfigInit(nil, nil)
if err != nil {
@@ -175,7 +190,8 @@ func Server() (*gin.Engine, error) {
r.GET("/MAPPort", func(c *gin.Context) {
Ports := c.DefaultQuery("port", "0")
url, _, err := MapPort(Ports)
DomainName := c.DefaultQuery("domain_name", "0")
url, _, err := MapPort(Ports, DomainName)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
@@ -183,6 +199,42 @@ func Server() (*gin.Engine, error) {
c.String(http.StatusOK, url)
})
r.GET("/AddProxy", func(c *gin.Context) {
DomainName := c.DefaultQuery("domain_name", "")
ip_address := c.DefaultQuery("ip_address", "")
Ports := c.DefaultQuery("port", "")
if DomainName == "" || ip_address == "" || Ports == "" {
c.String(http.StatusInternalServerError, fmt.Sprintf("All get parameters npt provided"+
" do ensure domain_name, ip_Address and port no is provided"))
}
SaveRegistration(DomainName, ip_address+":"+Ports)
//_, ok := ReverseProxies[DomainName]
//// To check if the subdomain entry exists
//if ok {
// c.String(http.StatusInternalServerError, fmt.Sprintf("The domain entry already exists as a reverse"+
// " proxy entry"))
//}
//
//// added proxy as a map entry
//ReverseProxies[DomainName] = ReverseProxy{IPAddress: ip_address, Port: Ports}
})
r.GET("/RemoveProxy", func(c *gin.Context) {
DomainName := c.DefaultQuery("domain_name", "")
_, ok := ReverseProxies[DomainName]
if !ok {
c.String(http.StatusInternalServerError, fmt.Sprintf("Domain name does exist in entries of proxies"))
} else {
delete(ReverseProxies, DomainName)
}
})
// If there is a proxy port specified
// then starts the FRP server
//if config.FRPServerPort != "0" {
@@ -233,6 +285,7 @@ func Server() (*gin.Engine, error) {
ProxyIpAddr.ServerPort = proxyPort
ProxyIpAddr.Name = config.MachineName
ProxyIpAddr.NAT = "False"
ProxyIpAddr.ProxyServer = "False"
ProxyIpAddr.EscapeImplementation = "FRP"
// Sorry Jan it's a string
@@ -240,7 +293,7 @@ func Server() (*gin.Engine, error) {
// to a boolean operator
// But I am way too tired
if config.BareMetal == "True" {
_, SSHPort, err := MapPort("22")
_, SSHPort, err := MapPort("22", "")
if err != nil {
return nil, err
}
@@ -269,13 +322,17 @@ func Server() (*gin.Engine, error) {
}
if config.ProxyPort != "" {
go ProxyRun(config.ProxyPort)
}
// Run gin server on the specified port
go r.Run(":" + config.ServerPort)
return r, nil
}
func MapPort(port string) (string, string, error) {
func MapPort(port string, domainName string) (string, string, error) {
//Get Server port based on the config file
config, err := config.ConfigInit(nil, nil)
if err != nil {