Skip to content

Commit

Permalink
add -login and -password server-side.
Browse files Browse the repository at this point in the history
  • Loading branch information
iebb committed May 21, 2022
1 parent 45382ad commit 0d52e31
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 80 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Self-hosted reverse-proxy for F1 web viewer, includes a web server at port 13331

### Running Locally

Download binary from https://github.com/iebb/F1WebViewer-SelfHosted/releases, or build your own, or just `go run main.go`
Download binary from https://github.com/iebb/F1WebViewer-SelfHosted/releases, or build your own, or just `go run .`

### Running on a Server (Requires SSL to make DRM work):
Encrypted Media requires secure context to work, which means https is required except localhost.
Expand Down
68 changes: 68 additions & 0 deletions cert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package main

import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"math/big"
"net"
"sync"
"time"
)

const RSABits = 2048
const ValidFor = time.Hour * 1440

var certCache sync.Map

func GetSelfSignedCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
if cert, ok := certCache.Load(clientHello.ServerName); ok {
return cert.(*tls.Certificate), nil
}
priv, err := rsa.GenerateKey(rand.Reader, RSABits)
if err != nil {
return nil, err
}

notBefore := time.Now()
notAfter := notBefore.Add(ValidFor)

serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, err
}

template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"Acme Co"},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}

host := clientHello.ServerName
if ip := net.ParseIP(host); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, host)
}

derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
return nil, err
}

cert := &tls.Certificate{
Certificate: [][]byte{derBytes},
PrivateKey: priv,
}
certCache.Store(clientHello.ServerName, cert)
return cert, err
}
54 changes: 54 additions & 0 deletions login.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package main

import (
"bytes"
"encoding/json"
"io"
"net/http"
)

type Crediential struct {
Login string `json:"Login"`
Password string `json:"Password"`
}

const LoginUrl = "https://f1tokenx.deta.dev/authenticate"

func handleLogin(w http.ResponseWriter, r *http.Request) {
var p Crediential

if login != "" && password != "" {
p.Login = login
p.Password = password
} else {
err := json.NewDecoder(r.Body).Decode(&p)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
}

jsonStr, _ := json.Marshal(p)
req, _ := http.NewRequest("POST", LoginUrl, bytes.NewBuffer(jsonStr))
for k, vv := range r.Header {
for _, v := range vv {
req.Header.Add(k, v)
}
}
client := &http.Client{}
resp, _ := client.Do(req)

for k, vv := range resp.Header {
for _, v := range vv {
w.Header().Add(k, v)
}
}
w.WriteHeader(resp.StatusCode)
_, _ = io.Copy(w, resp.Body)
_ = resp.Body.Close()
}

func serverSideLoginRewriter(resp *http.Response) (err error) {
resp.Header.Add("Set-Cookie", "server_side_login=1; Max-Age=86400; Path=/")
return nil
}
92 changes: 13 additions & 79 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,86 +1,25 @@
package main

import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"flag"
"fmt"
"github.com/gorilla/mux"
"github.com/pkg/browser"
"golang.org/x/crypto/acme/autocert"
"log"
"math/big"
"net"
"net/http"
"net/http/httputil"
"net/url"
"regexp"
"strings"
"sync"
"time"
)

var builtInSSL = false
var selfSSL = false
var port = 13331

const RSABits = 2048
const ValidFor = time.Hour * 1440

var certCache sync.Map

func GetSelfSignedCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
if cert, ok := certCache.Load(clientHello.ServerName); ok {
return cert.(*tls.Certificate), nil
}
priv, err := rsa.GenerateKey(rand.Reader, RSABits)
if err != nil {
return nil, err
}

notBefore := time.Now()
notAfter := notBefore.Add(ValidFor)

serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, err
}

template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"Acme Co"},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}

host := clientHello.ServerName
if ip := net.ParseIP(host); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, host)
}

derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
return nil, err
}

cert := &tls.Certificate{
Certificate: [][]byte{derBytes},
PrivateKey: priv,
}
certCache.Store(clientHello.ServerName, cert)
return cert, err
}
var listenAddr = "localhost:13331"
var login = ""
var password = ""

func init() {
flag.BoolVar(&builtInSSL, "ssl", false,
Expand All @@ -89,7 +28,9 @@ func init() {
flag.BoolVar(&selfSSL, "self-sign", false,
"self-signed ssl support. would display a warning on browsers",
)
flag.IntVar(&port, "port", 13331, "port number")
flag.StringVar(&listenAddr, "listen", "localhost:13331", "which IP and port to listen?")
flag.StringVar(&login, "login", "", "server-side login")
flag.StringVar(&password, "password", "", "server-side password")
}

func main() {
Expand Down Expand Up @@ -126,31 +67,24 @@ func main() {
}
proxy.ServeHTTP(w, r)
}
staticRemote, _ := url.Parse("https://f1vp.netlify.app/")

staticRemote, _ := url.Parse("https://f1vp.netlify.app")
staticProxy := httputil.NewSingleHostReverseProxy(staticRemote)
if login != "" && password != "" {
staticProxy.ModifyResponse = serverSideLoginRewriter
}
staticHandler := func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s FE* - %s\n", r.RemoteAddr, r.URL.String())
r.Host = staticRemote.Host
staticProxy.ServeHTTP(w, r)
}

fnRemote, _ := url.Parse("https://fwv-us.deta.dev/")
fnProxy := httputil.NewSingleHostReverseProxy(fnRemote)
fnHandler := func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s BE* - %s\n", r.RemoteAddr, r.URL.String())
r.Host = fnRemote.Host
fnProxy.ServeHTTP(w, r)
}

r := mux.NewRouter()
r.HandleFunc("/proxy/{url:https?://?.*}", handler)
r.PathPrefix("/authenticate").HandlerFunc(fnHandler)
r.PathPrefix("/66571939").HandlerFunc(fnHandler)
r.PathPrefix("/authenticate").HandlerFunc(handleLogin)
r.PathPrefix("/").HandlerFunc(staticHandler)
r.SkipClean(true)

listenAddr := fmt.Sprintf(":%d", port)

if builtInSSL {
certManager := autocert.Manager{
Prompt: autocert.AcceptTOS,
Expand All @@ -177,7 +111,7 @@ func main() {
}
log.Fatal(server.ListenAndServeTLS("", ""))
} else {
_ = browser.OpenURL(fmt.Sprintf("http://localhost:%d/", port))
_ = browser.OpenURL(fmt.Sprintf("http://%s/", listenAddr))
log.Println("Reverse Proxy Server running at " + listenAddr + "\n")
log.Fatal(http.ListenAndServe(listenAddr, r))
}
Expand Down

0 comments on commit 0d52e31

Please sign in to comment.