嗅探HTTP SSL连接

时间:2019-03-26 21:17:10

标签: ssl go tcp

假设我拥有一个net.Listener套接字,如何检测到传入连接正在使用ssl。

我使用下面的代码可以很好地调度bt / http连接。

代码在缓冲的conn上执行字节到字节的比较,如果什么也没找到,它将默认为bt侦听器。

我希望它能够分派ssl tls连接,如果我正确的话,最好是在sni支持下执行主机分派。

package server

import (
    "bufio"
    "bytes"
    "log"
    "net"
)

type SocketDispatcher struct {
    net.Listener
    Dispatchers []*Dispatcher
}

func (l *SocketDispatcher) Accept() (net.Conn, error) {
    for {
        conn, err := l.Listener.Accept()
        if err != nil {
            return nil, err
        }
        var r *bufio.Reader
        r, conn = makePeekedConn(conn)
        if d := l.Snif(r); d != nil {
            d.Handle(conn)
            continue
        }
        return conn, err
    }
}

func (l *SocketDispatcher) Snif(r *bufio.Reader) *Dispatcher {
    for _, d := range l.Dispatchers {
        if d.Snif(r) {
            return d
        }
    }
    return nil
}

type Dispatcher struct {
    Snif     func(r *bufio.Reader) bool
    accepted chan net.Conn
}

func (d *Dispatcher) Handle(conn net.Conn) error {
    go func() {
        d.accepted <- conn
    }()
    return nil
}

func (d *Dispatcher) Accept() (net.Conn, error) {
    conn := <-d.accepted
    return conn, nil
}

func CatchAll() *Dispatcher {
    return &Dispatcher{
        Snif: func(r *bufio.Reader) bool {
            return true
        },
        accepted: make(chan net.Conn),
    }
}

func HTTPDispatcher() *Dispatcher {
    return &Dispatcher{
        Snif: func(r *bufio.Reader) bool {
            return HTTPSnif(r)
        },
        accepted: make(chan net.Conn),
    }
}

//HTTPSnif detects http requests
func HTTPSnif(t *bufio.Reader) bool {
    ms := []string{"GET", "PUT", "HEAD", "POST", "PATCH", "OPTION", "DELETE"}
    longuest := 0
    for _, m := range ms {
        if longuest < len(m) {
            longuest = len(m)
        }
    }

    remains := [][]byte{}
    for _, m := range ms {
        b := []byte(m + " ")
        remains = append(remains, b)
    }

    for e := 1; e <= longuest; e++ {
        p, err := t.Peek(e)
        if err != nil {
            log.Println("peek", err)
            return false
        }
        remains = filter(remains, p)
        if len(remains) == 0 {
            return false
        }
        if len(remains) == 1 {
            return true
        }
    }

    return true
}

func filter(remains [][]byte, cur []byte) [][]byte {
    rests := [][]byte{}
    for _, r := range remains {
        if bytes.HasPrefix(r, cur) || bytes.Equal(r, cur) {
            rests = append(rests, r)
        }
    }
    return rests
}

func peekCompare(t *bufio.Reader, search []byte) bool {
    var p []byte
    for i := 1; i <= len(search); i++ {
        var err error
        p, err = t.Peek(i)
        if err != nil {
            return false
        }
        if !bytes.HasPrefix(search, p) {
            return false
        }
    }
    return bytes.Equal(search, p)
}

0 个答案:

没有答案