change Windows Start()/Stop() behavior, update debug output
This commit is contained in:
parent
d66053efd1
commit
a62f46c070
|
@ -162,21 +162,27 @@ func (p *program) Init(env svc.Environment) error {
|
||||||
|
|
||||||
os.Stdout = f
|
os.Stdout = f
|
||||||
os.Stderr = f
|
os.Stderr = f
|
||||||
|
dbg.OutFile = f
|
||||||
|
dbg.ErrFile = f
|
||||||
log.SetOutput(f)
|
log.SetOutput(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var started bool
|
||||||
|
|
||||||
func (p *program) Start() error {
|
func (p *program) Start() error {
|
||||||
log.Printf("Starting...\n")
|
log.Printf("Starting...\n")
|
||||||
go fetchDirectivesAndRun()
|
if !started {
|
||||||
|
started = true
|
||||||
|
go fetchDirectivesAndRun()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *program) Stop() error {
|
func (p *program) Stop() error {
|
||||||
log.Printf("Can't stop. Exiting instead.\n")
|
log.Printf("Can't stop. Doing nothing instead.\n")
|
||||||
os.Exit(exitOk)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +208,7 @@ func parseFlagsAndENVs() {
|
||||||
var resolvers []string
|
var resolvers []string
|
||||||
var dnsPropagationDelay time.Duration
|
var dnsPropagationDelay time.Duration
|
||||||
|
|
||||||
debug := flag.Bool("debug", true, "show debug output")
|
debug := flag.Bool("debug", false, "show debug output")
|
||||||
verbose := flag.Bool("verbose", false, "log excessively")
|
verbose := flag.Bool("verbose", false, "log excessively")
|
||||||
|
|
||||||
spfDomain := flag.String("spf-domain", "", "domain with SPF-like list of IP addresses which are allowed to connect to clients")
|
spfDomain := flag.String("spf-domain", "", "domain with SPF-like list of IP addresses which are allowed to connect to clients")
|
||||||
|
@ -237,10 +243,6 @@ func parseFlagsAndENVs() {
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if !dbg.Debug {
|
|
||||||
dbg.Debug = *verbose || *debug
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(*envpath) > 0 {
|
if len(*envpath) > 0 {
|
||||||
if err := godotenv.Load(*envpath); nil != err {
|
if err := godotenv.Load(*envpath); nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "%v", err)
|
fmt.Fprintf(os.Stderr, "%v", err)
|
||||||
|
@ -248,6 +250,21 @@ func parseFlagsAndENVs() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dbg.Init()
|
||||||
|
|
||||||
|
if !dbg.Verbose {
|
||||||
|
if *verbose {
|
||||||
|
dbg.Verbose = true
|
||||||
|
dbg.Printf("--verbose: extra output enabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !dbg.Debug {
|
||||||
|
if *debug {
|
||||||
|
dbg.Verbose = true
|
||||||
|
dbg.Debug = true
|
||||||
|
dbg.Printf("--debug: byte output will be printed in full as hex")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spfRecords := iplist.Init(*spfDomain)
|
spfRecords := iplist.Init(*spfDomain)
|
||||||
if len(spfRecords) > 0 {
|
if len(spfRecords) > 0 {
|
||||||
|
|
|
@ -4,49 +4,140 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Debug is a flag for whether or not verbose logging should be activated
|
// Verbose is a flag for whether or not verbose logging should be activated
|
||||||
|
var Verbose bool
|
||||||
|
|
||||||
|
// Debug does not truncate byte strings
|
||||||
var Debug bool
|
var Debug bool
|
||||||
|
|
||||||
var rawBytes bool
|
// VerboseVerbose does not truncate strings
|
||||||
var allBytes bool
|
var VerboseVerbose bool
|
||||||
|
|
||||||
|
// OutFile is the output path for StdOut
|
||||||
|
var OutFile *os.File
|
||||||
|
|
||||||
|
// ErrFile is the output path for StdErr
|
||||||
|
var ErrFile *os.File
|
||||||
|
|
||||||
|
type out int
|
||||||
|
|
||||||
|
const (
|
||||||
|
stdout out = iota
|
||||||
|
stderr
|
||||||
|
)
|
||||||
|
|
||||||
|
type output struct {
|
||||||
|
out out
|
||||||
|
msg string
|
||||||
|
other []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var log chan output
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
log = make(chan output)
|
||||||
|
|
||||||
Init()
|
Init()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
o := <-log
|
||||||
|
// because OutFile and ErrFile may be the same
|
||||||
|
msg := strings.TrimSuffix(o.msg, "\n") + "\n"
|
||||||
|
b := []byte(fmt.Sprintf(msg, o.other...))
|
||||||
|
if stdout == o.out {
|
||||||
|
OutFile.Write(b)
|
||||||
|
} else {
|
||||||
|
ErrFile.Write(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printf will print to log.Printf
|
||||||
|
func Printf(tpl string, other ...interface{}) {
|
||||||
|
log <- output{
|
||||||
|
out: stdout,
|
||||||
|
msg: tpl,
|
||||||
|
other: other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf will print to fmt.Fprintf(stderr)
|
||||||
|
func Warnf(tpl string, other ...interface{}) {
|
||||||
|
log <- output{
|
||||||
|
out: stderr,
|
||||||
|
msg: "[warn] " + tpl,
|
||||||
|
other: other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf will print to fmt.Fprintf(std)
|
||||||
|
func Debugf(tpl string, other ...interface{}) {
|
||||||
|
log <- output{
|
||||||
|
out: stderr,
|
||||||
|
msg: "[debug] " + tpl,
|
||||||
|
other: other,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init will set debug vars from ENVs and print out whatever is set
|
// Init will set debug vars from ENVs and print out whatever is set
|
||||||
func Init() {
|
func Init() {
|
||||||
if !Debug {
|
if nil == OutFile {
|
||||||
Debug = ("true" == os.Getenv("VERBOSE"))
|
OutFile = os.Stdout
|
||||||
}
|
}
|
||||||
if !allBytes {
|
if nil == ErrFile {
|
||||||
allBytes = ("true" == os.Getenv("VERBOSE_BYTES"))
|
ErrFile = os.Stderr
|
||||||
}
|
|
||||||
if !rawBytes {
|
|
||||||
rawBytes = ("true" == os.Getenv("VERBOSE_RAW"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug {
|
if !Verbose {
|
||||||
fmt.Fprintf(os.Stderr, "DEBUG=true\n")
|
if "true" == os.Getenv("VERBOSE") {
|
||||||
|
Printf("VERBOSE=true")
|
||||||
|
Verbose = true
|
||||||
|
}
|
||||||
|
if Verbose {
|
||||||
|
fmt.Fprintf(os.Stderr, "VERBOSE: extra logging enabled\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if allBytes || rawBytes {
|
|
||||||
fmt.Fprintf(os.Stderr, "VERBOSE_BYTES=true\n")
|
if !VerboseVerbose {
|
||||||
|
if "true" == strings.ToLower(os.Getenv("VERBOSE_VERBOSE")) {
|
||||||
|
Printf("VERBOSE_VERBOSE=true")
|
||||||
|
VerboseVerbose = true
|
||||||
|
} else if "true" == strings.ToLower(os.Getenv("VERBOSE_RAW")) {
|
||||||
|
Printf("VERBOSE_RAW=true # Deprecated: Use VERBOSE_VERBOSE=true")
|
||||||
|
VerboseVerbose = true
|
||||||
|
}
|
||||||
|
if VerboseVerbose {
|
||||||
|
fmt.Fprintf(os.Stderr, "VERBOSE_VERBOSE: output will NOT be truncated\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if rawBytes {
|
|
||||||
fmt.Fprintf(os.Stderr, "VERBOSE_RAW=true\n")
|
if !Debug {
|
||||||
|
if "true" == strings.ToLower(os.Getenv("DEBUG")) {
|
||||||
|
Printf("DEBUG=true")
|
||||||
|
Debug = true
|
||||||
|
} else if "true" == strings.ToLower(os.Getenv("VERBOSE_BYTES")) {
|
||||||
|
Printf("VERBOSE_BYTES=true # Deprecated: Use DEBUG=true")
|
||||||
|
Debug = true
|
||||||
|
}
|
||||||
|
if Debug {
|
||||||
|
fmt.Fprintf(os.Stderr, "DEBUG: byte output will be printed as hex\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trunc will take up to the first and last 20 bytes of the input to product 80 char hex output
|
// Trunc will take up to the first and last 20 bytes of the input to product 80 char hex output
|
||||||
func Trunc(b []byte, n int) string {
|
func Trunc(b []byte, n int) string {
|
||||||
bin := b[:n]
|
bin := b[:n]
|
||||||
if allBytes || rawBytes {
|
if Debug || VerboseVerbose {
|
||||||
if rawBytes {
|
if Debug {
|
||||||
return string(bin)
|
return hex.EncodeToString(bin)
|
||||||
}
|
}
|
||||||
return hex.EncodeToString(bin)
|
return string(bin)
|
||||||
}
|
}
|
||||||
if n > 40 {
|
if n > 40 {
|
||||||
return hex.EncodeToString(bin[:19]) + ".." + hex.EncodeToString(bin[n-19:])
|
return hex.EncodeToString(bin[:19]) + ".." + hex.EncodeToString(bin[n-19:])
|
||||||
|
|
|
@ -6,14 +6,33 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrNotClientHello happens when the TLS packet is not a ClientHello
|
||||||
|
var ErrNotClientHello = errors.New("Not a ClientHello")
|
||||||
|
|
||||||
|
// ErrMalformedHello is a failure to parse the ClientHello
|
||||||
|
var ErrMalformedHello = errors.New("malformed TLS ClientHello")
|
||||||
|
|
||||||
|
// ErrNoExtensions means that SNI is missing from the ClientHello
|
||||||
|
var ErrNoExtensions = errors.New("no TLS extensions")
|
||||||
|
|
||||||
// GetHostname uses SNI to determine the intended target of a new TLS connection.
|
// GetHostname uses SNI to determine the intended target of a new TLS connection.
|
||||||
func GetHostname(b []byte) (string, error) {
|
func GetHostname(b []byte) (hostname string, err error) {
|
||||||
|
// Since this is a hot piece of code (runs frequently)
|
||||||
|
// we protect against out-of-bounds reads with recover
|
||||||
|
// rather than adding additional out-of-bounds checks
|
||||||
|
// in addition to the ones that Go already provides
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); nil != r {
|
||||||
|
err = ErrMalformedHello
|
||||||
|
}
|
||||||
|
}()
|
||||||
rest := b[5:]
|
rest := b[5:]
|
||||||
|
n := len(rest)
|
||||||
current := 0
|
current := 0
|
||||||
handshakeType := rest[0]
|
handshakeType := rest[0]
|
||||||
current++
|
current++
|
||||||
if handshakeType != 0x1 {
|
if handshakeType != 0x1 {
|
||||||
return "", errors.New("Not a ClientHello")
|
return "", ErrNotClientHello
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip over another length
|
// Skip over another length
|
||||||
|
@ -35,14 +54,14 @@ func GetHostname(b []byte) (string, error) {
|
||||||
current++
|
current++
|
||||||
current += compressionMethodLength
|
current += compressionMethodLength
|
||||||
|
|
||||||
if current > len(rest) {
|
// TODO shouldn't this be current >= n ??
|
||||||
return "", errors.New("no extensions")
|
if current > n {
|
||||||
|
return "", ErrNoExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
current += 2
|
current += 2
|
||||||
|
|
||||||
hostname := ""
|
for current < n {
|
||||||
for current < len(rest) && hostname == "" {
|
|
||||||
extensionType := (int(rest[current]) << 8) + int(rest[current+1])
|
extensionType := (int(rest[current]) << 8) + int(rest[current+1])
|
||||||
current += 2
|
current += 2
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,8 @@ package telebit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"encoding/hex"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rootprojects.org/root/telebit/internal/dbg"
|
"git.rootprojects.org/root/telebit/internal/dbg"
|
||||||
|
@ -139,14 +138,14 @@ func (c *ConnWrap) isEncrypted() bool {
|
||||||
c.SetDeadline(time.Now().Add(5 * time.Second))
|
c.SetDeadline(time.Now().Add(5 * time.Second))
|
||||||
n := 6
|
n := 6
|
||||||
b, err := c.Peek(n)
|
b, err := c.Peek(n)
|
||||||
|
defer c.SetDeadline(time.Time{})
|
||||||
if dbg.Debug {
|
if dbg.Debug {
|
||||||
fmt.Fprintf(os.Stderr, "[debug] [wrap] Peek(%d): %s %v\n", n, string(b), err)
|
dbg.Debugf("[wrap] Peek(%d): %q %v\n", n, hex.EncodeToString(b), err)
|
||||||
}
|
}
|
||||||
if nil != err {
|
if nil != err {
|
||||||
// TODO return error on error?
|
// TODO return error on error?
|
||||||
return encrypted
|
return encrypted
|
||||||
}
|
}
|
||||||
defer c.SetDeadline(time.Time{})
|
|
||||||
if len(b) >= n {
|
if len(b) >= n {
|
||||||
// SSL v3.x / TLS v1.x
|
// SSL v3.x / TLS v1.x
|
||||||
// 0: TLS Byte
|
// 0: TLS Byte
|
||||||
|
|
|
@ -120,7 +120,7 @@ func (m *RouteMux) Serve(client net.Conn) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("No match found for %q %q\n", wconn.Scheme(), wconn.Servername())
|
fmt.Printf("No match found for scheme=%q servername=%q\n", wconn.Scheme(), wconn.Servername())
|
||||||
return client.Close()
|
return client.Close()
|
||||||
|
|
||||||
// TODO Chi-style route handling
|
// TODO Chi-style route handling
|
||||||
|
|
Loading…
Reference in New Issue