duanou1904 2019-03-26 21:17
浏览 42

嗅探HTTP SSL连接

given that i own a net.Listener socket, how can i detect that an incoming connection is using ssl.

I work with below code which works fine to dispatch bt/http connections.

The code performs byte-to-byte comparison on the buffered conn, when nothing is found it defaults to the bt listener.

I want it to be able to dispatch ssl tls connections, ideally with sni support to perform host dispatching, if i m correct.

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条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 目详情-五一模拟赛详情页
    • ¥15 有了解d3和topogram.js库的吗?有偿请教
    • ¥100 任意维数的K均值聚类
    • ¥15 stamps做sbas-insar,时序沉降图怎么画
    • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
    • ¥15 关于#Java#的问题,如何解决?
    • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
    • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
    • ¥15 cmd cl 0x000007b
    • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line