Skip to content

Commit

Permalink
Add sni support
Browse files Browse the repository at this point in the history
Signed-off-by: Sherlock Holo <[email protected]>
  • Loading branch information
Sherlock-Holo committed Feb 27, 2019
1 parent 17a7281 commit ea09133
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 15 deletions.
11 changes: 9 additions & 2 deletions config/example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ path = "/websocket"
key = "script/client/client.key"
crt = "script/client/client.crt"

# set a ca to debug camouflage, non-recommand use in product server
# set a ca to debug camouflage, non-recommand use in product server (optional)
debug_ca = "script/ca/ca.crt"

listen_addr = "127.0.0.1:9875"

# connect timeout
# connect timeout (optional)
timeout = "30s"


Expand All @@ -25,8 +25,15 @@ client_ca_crt = "script/ca/ca.crt"
key = "script/server/server.key"
crt = "script/server/server.crt"

# crl support (optional)
crl = "script/server/crl.pem"

path = "/websocket"

# serve a static web site (optional)
web_root = "/home/sherlock/git/blog/output"

# sni feature for web service (optional)
web_host = "blog.example.com:9876"
web_key = "script/web/web.key"
web_crt = "script/web/web.crt"
6 changes: 4 additions & 2 deletions config/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ type Config struct {
Crt string `toml:"crt"`
Path string `toml:"path"`
WebRoot string `toml:"web_root"`

Crl string `toml:"crl"`
WebKey string `toml:"web_key"`
WebCrt string `toml:"web_crt"`
WebHost string `toml:"web_host"`
Crl string `toml:"crl"`
}

type tomlConfig struct {
Expand Down
77 changes: 66 additions & 11 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"log"
"net"
"net/http"
"net/url"
"strings"

"github.com/Sherlock-Holo/camouflage/config/server"
"github.com/Sherlock-Holo/camouflage/utils"
Expand All @@ -28,20 +30,49 @@ type Server struct {
}

func (s *Server) checkRequest(w http.ResponseWriter, r *http.Request) {
if len(r.TLS.PeerCertificates) == 0 {
s.webHandle(w, r)
return
}
if s.enableWebCertificate() {
switch r.Host {
case s.config.WebHost:
s.webHandle(w, r)
return

// check client certificate in crl or not
if s.crl != nil {
for _, certificate := range r.TLS.PeerCertificates {
if utils.IsRevokedCertificate(certificate, s.crl) {
case s.config.Host:
if !s.checkCertificate(r) {
return
}

s.proxyHandle(w, r)
return

default:
webUrl := url.URL{
Scheme: "https",
Path: r.URL.Path,
}
if strings.HasSuffix(s.config.WebHost, ":443") {
webUrl.Host = strings.Split(s.config.WebHost, ":")[0]
} else {
webUrl.Host = s.config.WebHost
}

http.Redirect(w, r, webUrl.String(), http.StatusFound)
return
}
}

if !s.checkCertificate(r) {
s.webHandle(w, r)
return
}

s.proxyHandle(w, r)
}

func (s *Server) webHandle(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, s.config.WebRoot)
}

func (s *Server) proxyHandle(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != s.config.Path || !websocket.IsWebSocketUpgrade(r) {
w.WriteHeader(http.StatusNotFound)
return
Expand All @@ -57,7 +88,7 @@ func (s *Server) checkRequest(w http.ResponseWriter, r *http.Request) {
for {
l, err := manager.Accept()
if err != nil {
log.Println(err)
log.Printf("manager accept failed: %v", err)
manager.Close()
return
}
Expand All @@ -66,8 +97,17 @@ func (s *Server) checkRequest(w http.ResponseWriter, r *http.Request) {
}
}

func (s *Server) webHandle(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, s.config.WebRoot)
func (s *Server) checkCertificate(r *http.Request) bool {
// check client certificate in crl or not
if s.crl != nil {
for _, certificate := range r.TLS.PeerCertificates {
if utils.IsRevokedCertificate(certificate, s.crl) {
return false
}
}
}

return true
}

func handle(l link.Link) {
Expand Down Expand Up @@ -137,9 +177,20 @@ func New(cfg *server.Config) (server *Server) {

tlsConfig.Certificates = append(tlsConfig.Certificates, serverCertificate)

if server.enableWebCertificate() {
// load web certificate
webCertificate, err := tls.LoadX509KeyPair(server.config.WebCrt, server.config.WebKey)
if err != nil {
log.Fatalf("read web key pair failed: %+v", errors.WithStack(err))
}
tlsConfig.Certificates = append(tlsConfig.Certificates, webCertificate)
}

// set client auth mode, use tls.VerifyClientCertIfGiven
tlsConfig.ClientAuth = tls.VerifyClientCertIfGiven

tlsConfig.BuildNameToCertificate()

// read crl
if cfg.Crl != "" {
crlBytes, err := ioutil.ReadFile(cfg.Crl)
Expand Down Expand Up @@ -168,3 +219,7 @@ func New(cfg *server.Config) (server *Server) {

return
}

func (s *Server) enableWebCertificate() bool {
return s.config.WebCrt != "" && s.config.WebKey != "" && s.config.WebRoot != "" && s.config.WebHost != ""
}

0 comments on commit ea09133

Please sign in to comment.