Merge pull request #136 from george-e-shaw-iv/master

Implemented TLS with autocert && partially fixed serving PHP
This commit is contained in:
George Shaw 2018-02-12 14:11:43 -06:00 committed by GitHub
commit cdddde0812
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 78 additions and 23 deletions

View file

@ -93,8 +93,8 @@ Key: __Implemented__ | __*Implemented, but needs work*__ | *Unimplemented* | ~~R
* Domains
* __Configuration of domains__
* __Configuration of sub-domains__
* *TLS/SSL certificate support*
* *Using LetsEncrypt (Certbot)*
* __TLS/SSL certificate support__
* __Using LetsEncrypt (autocert)__
* __Multi-domain support__
* Remote Access
* __SSH Access__

4
Gopkg.lock generated
View file

@ -16,7 +16,7 @@
[[projects]]
branch = "master"
name = "golang.org/x/crypto"
packages = ["bcrypt","blowfish"]
packages = ["acme","acme/autocert","bcrypt","blowfish"]
revision = "2509b142fb2b797aa7587dad548f113b2c0f20ce"
[[projects]]
@ -28,6 +28,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "e4b8a6fd1b416960accf57e305df9fb6c1c50fb9aecde348a0735eff39614d0d"
inputs-digest = "bc99bfe3269f7f4c24a0166bbfe5fd0cafdee6c803274787bff0ac01b8cb4ed6"
solver-name = "gps-cdcl"
solver-version = 1

View file

@ -54,6 +54,7 @@ sudo ./gpanel
- ssh-keygen command (already installed on most debian-based linux systems)
- openssh-server installed (installation guide below)
- golang (installation guide below)
- [php-cgi](http://us3.php.net/downloads.php) IF you want to be able to serve .php files
- OSX
- Currently there is no support for OSX, but it is planned for the future.
-----------------------------------

View file

@ -15,7 +15,11 @@ func main() {
const insecurePort = 2080
const securePort = 2443
server := gpserver.New()
server, err := gpserver.New()
if err != nil {
log.Printf("\nA non-fatal error has occurred whilst starting the server: %v\n\n", err.Error())
}
router := router.New(insecurePort, securePort)
if router == nil {

View file

@ -138,7 +138,14 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
return false
}
bundles[createBundleRequestData.Name] = gpaccount.New(newBundle+"/", createBundleRequestData.Name, databaseBundlePorts.Account, databaseBundlePorts.Public)
bundles[createBundleRequestData.Name], err = gpaccount.New(newBundle+"/", createBundleRequestData.Name, databaseBundlePorts.Account, databaseBundlePorts.Public)
if err != nil {
logger.Println(req.URL.Path + "::" + err.Error())
http.Error(res, err.Error(), http.StatusInternalServerError)
return false
}
_ = bundles[createBundleRequestData.Name].Start()
_ = bundles[createBundleRequestData.Name].Public.Start()

View file

@ -26,7 +26,7 @@ type Controller struct {
}
// New returns a new Controller reference.
func New(dir, name string, accPort, pubPort int) *Controller {
func New(dir, name string, accPort, pubPort int) (*Controller, error) {
f, err := os.OpenFile(dir+"logs/account_errors.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
fmt.Println("error whilst trying to start server logging instance:", err.Error())
@ -35,12 +35,17 @@ func New(dir, name string, accPort, pubPort int) *Controller {
apiLogger := log.New(f, "API :: ", 3)
accountLogger := log.New(f, "ACCOUNT :: ", 3)
pub, err := public.New("/home/"+name+"/", dir, name, pubPort)
if err != nil {
return nil, err
}
controller := Controller{
Directory: dir,
DocumentRoot: "account/",
Name: name,
Port: accPort,
Public: public.New("/home/"+name+"/", dir, pubPort),
Public: pub,
GracefulShutdownTimeout: 5 * time.Second,
Status: 0,
AccountLogger: accountLogger,
@ -55,5 +60,5 @@ func New(dir, name string, accPort, pubPort int) *Controller {
MaxHeaderBytes: 0,
}
return &controller
return &controller, nil
}

View file

@ -8,7 +8,8 @@ import (
"github.com/Ennovar/gPanel/pkg/gpaccount"
)
func (con *Controller) detectBundles() {
func (con *Controller) detectBundles() error {
var err error = nil
bundles := make(map[string]*gpaccount.Controller)
dirs, err := ioutil.ReadDir("bundles/")
@ -21,7 +22,7 @@ func (con *Controller) detectBundles() {
dirPath := "bundles/" + dir.Name() + "/"
err, accPort, pubPort := bundle.GetPorts(dirPath)
curBundle := gpaccount.New(dirPath, dir.Name(), accPort, pubPort)
curBundle, err := gpaccount.New(dirPath, dir.Name(), accPort, pubPort)
err = curBundle.Start()
err2 := curBundle.Public.Start()
@ -34,4 +35,5 @@ func (con *Controller) detectBundles() {
}
con.Bundles = bundles
return err
}

View file

@ -16,7 +16,9 @@ type Controller struct {
APILogger *log.Logger
}
func New() *Controller {
func New() (*Controller, error) {
var err error = nil
f, err := os.OpenFile("server/logs/server_errors.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error whilst trying to start server logging instance:%v", err.Error())
@ -30,8 +32,8 @@ func New() *Controller {
APILogger: log.New(f, "API :: ", 3),
}
c.detectBundles()
err = c.detectBundles()
c.setDefaults()
return &c
return &c, err
}

View file

@ -2,17 +2,22 @@
package public
import (
"crypto/tls"
"log"
"net/http"
"os"
"path/filepath"
"strconv"
"time"
"github.com/Ennovar/gPanel/pkg/database"
"golang.org/x/crypto/acme/autocert"
)
type Controller struct {
Directory string
AccountDirectory string
Name string
Port int
GracefulShutdownTimeout time.Duration
Status int
@ -22,7 +27,7 @@ type Controller struct {
}
// New function returns a new PublicWeb type.
func New(dir, accountDir string, port int) *Controller {
func New(dir, accountDir, name string, port int) (*Controller, error) {
ph, lh, err := getLogHandles(dir)
if err != nil {
log.Fatalf("Error trying to start logging instances within %v: %v", dir, err.Error())
@ -31,6 +36,7 @@ func New(dir, accountDir string, port int) *Controller {
controller := Controller{
Directory: dir,
AccountDirectory: accountDir,
Name: name,
Port: port,
GracefulShutdownTimeout: 5 * time.Second,
Status: 0,
@ -38,15 +44,40 @@ func New(dir, accountDir string, port int) *Controller {
LoadTimeLogger: lh,
}
_ = os.Mkdir("/home/"+controller.Name+"/tls-cache", 0666)
ds, err := database.Open("server/" + database.DB_DOMAINS)
if err != nil {
return nil, err
}
defer ds.Close()
domainMap, err := ds.ListDomains(name)
if err != nil {
return nil, err
}
var domains []string
for k := range domainMap {
domains = append(domains, k)
}
certManager := &autocert.Manager{
Cache: autocert.DirCache("/home/" + name + "/tls-cache"),
Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist(domains...),
}
controller.Server = http.Server{
Addr: "localhost:" + strconv.Itoa(controller.Port),
Handler: &controller,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
MaxHeaderBytes: 0,
TLSConfig: &tls.Config{GetCertificate: certManager.GetCertificate},
}
return &controller
return &controller, nil
}
// Function getLogHandles returns the handle for the public logger, load logger,

View file

@ -27,16 +27,20 @@ func (con *Controller) ServePHP(res http.ResponseWriter, path string) {
line := s.Text()
split++
// Status will be first line
// Status will be first line, if it exists
if status == 0 {
m := reg.FindStringSubmatch(line)
var err error
status, err = strconv.Atoi(m[1])
if err != nil {
if len(m) == 0 {
// Status did not exist, so setting default status
status = 200
} else {
var err error
status, err = strconv.Atoi(m[1])
if err != nil {
status = 200
}
continue
}
continue
}
// Blank line between headers and body
@ -47,7 +51,6 @@ func (con *Controller) ServePHP(res http.ResponseWriter, path string) {
sep := strings.Index(line, ": ")
res.Header().Add(line[:sep], line[sep+2:])
continue
}
if err := s.Err(); err != nil {