1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-20 06:25:24 +00:00
v2fly/transport/internet/headers/http/http.go

322 lines
7.2 KiB
Go
Raw Normal View History

2016-10-31 21:26:46 +00:00
package http
//go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen
2017-04-08 23:43:25 +00:00
2016-10-31 21:26:46 +00:00
import (
"bufio"
2016-10-31 21:26:46 +00:00
"bytes"
2017-01-12 21:47:10 +00:00
"context"
2016-11-03 22:14:27 +00:00
"io"
2016-11-02 21:26:21 +00:00
"net"
2016-11-06 12:38:32 +00:00
"net/http"
2016-12-06 10:03:42 +00:00
"strings"
2016-11-06 12:38:32 +00:00
"time"
2016-12-09 11:08:25 +00:00
"github.com/v2fly/v2ray-core/v5/common"
"github.com/v2fly/v2ray-core/v5/common/buf"
2016-10-31 21:26:46 +00:00
)
const (
2017-04-27 09:37:25 +00:00
// CRLF is the line ending in HTTP header
CRLF = "\r\n"
// ENDING is the double line ending between HTTP header and body.
2016-10-31 21:26:46 +00:00
ENDING = CRLF + CRLF
2016-12-16 16:01:47 +00:00
2016-12-19 11:16:57 +00:00
// max length of HTTP header. Safety precaution for DDoS attack.
2016-12-16 16:01:47 +00:00
maxHeaderLength = 8192
2016-10-31 21:26:46 +00:00
)
2016-12-06 10:03:42 +00:00
var (
2017-04-08 23:43:25 +00:00
ErrHeaderToLong = newError("Header too long.")
ErrHeaderMisMatch = newError("Header Mismatch.")
2016-12-06 10:03:42 +00:00
)
2016-11-05 00:50:51 +00:00
type Reader interface {
2016-12-09 10:35:27 +00:00
Read(io.Reader) (*buf.Buffer, error)
2016-11-05 00:50:51 +00:00
}
type Writer interface {
Write(io.Writer) error
}
type NoOpReader struct{}
2017-04-27 09:37:25 +00:00
func (NoOpReader) Read(io.Reader) (*buf.Buffer, error) {
2016-11-05 00:50:51 +00:00
return nil, nil
}
type NoOpWriter struct{}
2017-04-27 09:37:25 +00:00
func (NoOpWriter) Write(io.Writer) error {
2016-11-05 00:50:51 +00:00
return nil
}
2016-11-03 22:14:27 +00:00
type HeaderReader struct {
req *http.Request
expectedHeader *RequestConfig
}
func (h *HeaderReader) ExpectThisRequest(expectedHeader *RequestConfig) *HeaderReader {
h.expectedHeader = expectedHeader
return h
2016-11-03 22:14:27 +00:00
}
func (h *HeaderReader) Read(reader io.Reader) (*buf.Buffer, error) {
2017-04-15 19:19:21 +00:00
buffer := buf.New()
2018-04-02 18:00:50 +00:00
totalBytes := int32(0)
2016-12-19 11:16:57 +00:00
endingDetected := false
var headerBuf bytes.Buffer
2016-12-16 16:01:47 +00:00
for totalBytes < maxHeaderLength {
2018-11-02 14:01:33 +00:00
_, err := buffer.ReadFrom(reader)
2016-11-03 22:14:27 +00:00
if err != nil {
2017-04-27 09:29:44 +00:00
buffer.Release()
2016-11-03 22:14:27 +00:00
return nil, err
}
2016-12-06 10:03:42 +00:00
if n := bytes.Index(buffer.Bytes(), []byte(ENDING)); n != -1 {
headerBuf.Write(buffer.BytesRange(0, int32(n+len(ENDING))))
buffer.Advance(int32(n + len(ENDING)))
2016-12-19 11:16:57 +00:00
endingDetected = true
2016-11-03 22:14:27 +00:00
break
}
2018-11-02 20:34:04 +00:00
lenEnding := int32(len(ENDING))
if buffer.Len() >= lenEnding {
totalBytes += buffer.Len() - lenEnding
headerBuf.Write(buffer.BytesRange(0, buffer.Len()-lenEnding))
2018-11-02 20:34:04 +00:00
leftover := buffer.BytesFrom(-lenEnding)
buffer.Clear()
copy(buffer.Extend(lenEnding), leftover)
if _, err := readRequest(bufio.NewReader(bytes.NewReader(headerBuf.Bytes()))); err != io.ErrUnexpectedEOF {
return nil, err
}
2016-11-03 22:14:27 +00:00
}
}
2016-12-19 11:16:57 +00:00
if !endingDetected {
buffer.Release()
return nil, ErrHeaderToLong
}
if h.expectedHeader == nil {
if buffer.IsEmpty() {
buffer.Release()
return nil, nil
}
return buffer, nil
}
// Parse the request
if req, err := readRequest(bufio.NewReader(bytes.NewReader(headerBuf.Bytes()))); err != nil {
return nil, err
} else { // nolint: revive
h.req = req
}
// Check req
path := h.req.URL.Path
hasThisURI := false
for _, u := range h.expectedHeader.Uri {
if u == path {
hasThisURI = true
}
}
if !hasThisURI {
return nil, ErrHeaderMisMatch
}
if buffer.IsEmpty() {
buffer.Release()
return nil, nil
}
2016-11-03 22:14:27 +00:00
return buffer, nil
}
type HeaderWriter struct {
2016-12-09 10:35:27 +00:00
header *buf.Buffer
2016-11-03 22:14:27 +00:00
}
2016-12-09 10:35:27 +00:00
func NewHeaderWriter(header *buf.Buffer) *HeaderWriter {
2016-11-04 20:59:19 +00:00
return &HeaderWriter{
header: header,
}
}
2017-04-13 20:17:58 +00:00
func (w *HeaderWriter) Write(writer io.Writer) error {
if w.header == nil {
2016-11-03 22:14:27 +00:00
return nil
}
2018-07-28 13:03:40 +00:00
err := buf.WriteAllBytes(writer, w.header.Bytes())
2017-04-13 20:17:58 +00:00
w.header.Release()
w.header = nil
2016-11-03 22:14:27 +00:00
return err
}
type Conn struct {
2016-11-02 21:26:21 +00:00
net.Conn
readBuffer *buf.Buffer
oneTimeReader Reader
oneTimeWriter Writer
errorWriter Writer
errorMismatchWriter Writer
errorTooLongWriter Writer
errReason error
2016-10-31 21:26:46 +00:00
}
func NewConn(conn net.Conn, reader Reader, writer Writer, errorWriter Writer, errorMismatchWriter Writer, errorTooLongWriter Writer) *Conn {
return &Conn{
Conn: conn,
oneTimeReader: reader,
oneTimeWriter: writer,
errorWriter: errorWriter,
errorMismatchWriter: errorMismatchWriter,
errorTooLongWriter: errorTooLongWriter,
2016-11-02 21:26:21 +00:00
}
}
2016-10-31 21:26:46 +00:00
func (c *Conn) Read(b []byte) (int, error) {
2017-04-13 20:17:58 +00:00
if c.oneTimeReader != nil {
buffer, err := c.oneTimeReader.Read(c.Conn)
2016-11-03 22:14:27 +00:00
if err != nil {
c.errReason = err
2016-11-03 22:14:27 +00:00
return 0, err
2016-11-02 21:26:21 +00:00
}
2017-04-13 20:17:58 +00:00
c.readBuffer = buffer
c.oneTimeReader = nil
2016-10-31 21:26:46 +00:00
}
2017-04-19 19:27:21 +00:00
if !c.readBuffer.IsEmpty() {
nBytes, _ := c.readBuffer.Read(b)
if c.readBuffer.IsEmpty() {
2017-04-13 20:17:58 +00:00
c.readBuffer.Release()
c.readBuffer = nil
2016-11-02 21:26:21 +00:00
}
2017-04-19 19:27:21 +00:00
return nBytes, nil
2016-11-02 21:26:21 +00:00
}
2016-10-31 21:26:46 +00:00
2017-04-13 20:17:58 +00:00
return c.Conn.Read(b)
2016-10-31 21:26:46 +00:00
}
2017-04-21 13:36:05 +00:00
// Write implements io.Writer.
func (c *Conn) Write(b []byte) (int, error) {
2017-04-13 20:17:58 +00:00
if c.oneTimeWriter != nil {
err := c.oneTimeWriter.Write(c.Conn)
c.oneTimeWriter = nil
2016-10-31 21:26:46 +00:00
if err != nil {
2016-11-02 21:26:21 +00:00
return 0, err
2016-10-31 21:26:46 +00:00
}
}
2017-04-13 20:17:58 +00:00
return c.Conn.Write(b)
2016-10-31 21:26:46 +00:00
}
2016-12-14 11:25:22 +00:00
// Close implements net.Conn.Close().
func (c *Conn) Close() error {
2017-04-13 20:17:58 +00:00
if c.oneTimeWriter != nil && c.errorWriter != nil {
2016-12-14 11:25:22 +00:00
// Connection is being closed but header wasn't sent. This means the client request
// is probably not valid. Sending back a server error header in this case.
// Write response based on error reason
switch c.errReason {
case ErrHeaderMisMatch:
c.errorMismatchWriter.Write(c.Conn)
case ErrHeaderToLong:
c.errorTooLongWriter.Write(c.Conn)
default:
c.errorWriter.Write(c.Conn)
}
2016-12-14 11:25:22 +00:00
}
2017-04-13 20:17:58 +00:00
return c.Conn.Close()
2016-10-31 21:26:46 +00:00
}
2016-12-14 11:25:22 +00:00
func formResponseHeader(config *ResponseConfig) *HeaderWriter {
2017-04-15 19:19:21 +00:00
header := buf.New()
2018-11-02 20:34:04 +00:00
common.Must2(header.WriteString(strings.Join([]string{config.GetFullVersion(), config.GetStatusValue().Code, config.GetStatusValue().Reason}, " ")))
common.Must2(header.WriteString(CRLF))
2016-10-31 21:26:46 +00:00
2016-11-02 21:26:21 +00:00
headers := config.PickHeaders()
for _, h := range headers {
2018-11-02 20:34:04 +00:00
common.Must2(header.WriteString(h))
common.Must2(header.WriteString(CRLF))
2016-10-31 21:26:46 +00:00
}
2016-12-14 11:25:22 +00:00
if !config.HasHeader("Date") {
2018-11-02 20:34:04 +00:00
common.Must2(header.WriteString("Date: "))
common.Must2(header.WriteString(time.Now().Format(http.TimeFormat)))
common.Must2(header.WriteString(CRLF))
2016-12-14 11:25:22 +00:00
}
2018-11-02 20:34:04 +00:00
common.Must2(header.WriteString(CRLF))
2016-11-03 22:14:27 +00:00
return &HeaderWriter{
header: header,
}
2016-10-31 21:26:46 +00:00
}
type Authenticator struct {
2016-12-14 11:25:22 +00:00
config *Config
}
func (a Authenticator) GetClientWriter() *HeaderWriter {
2017-04-15 19:19:21 +00:00
header := buf.New()
2017-04-13 20:17:58 +00:00
config := a.config.Request
common.Must2(header.WriteString(strings.Join([]string{config.GetMethodValue(), config.PickURI(), config.GetFullVersion()}, " ")))
2018-11-02 20:34:04 +00:00
common.Must2(header.WriteString(CRLF))
2016-10-31 21:26:46 +00:00
2016-11-02 21:26:21 +00:00
headers := config.PickHeaders()
2016-10-31 21:26:46 +00:00
for _, h := range headers {
2018-11-02 20:34:04 +00:00
common.Must2(header.WriteString(h))
common.Must2(header.WriteString(CRLF))
2016-11-06 12:38:32 +00:00
}
2018-11-02 20:34:04 +00:00
common.Must2(header.WriteString(CRLF))
2016-11-03 22:14:27 +00:00
return &HeaderWriter{
header: header,
}
2016-11-02 21:26:21 +00:00
}
2016-10-31 21:26:46 +00:00
func (a Authenticator) GetServerWriter() *HeaderWriter {
2017-04-13 20:17:58 +00:00
return formResponseHeader(a.config.Response)
2016-12-14 11:25:22 +00:00
}
func (a Authenticator) Client(conn net.Conn) net.Conn {
2017-04-13 20:17:58 +00:00
if a.config.Request == nil && a.config.Response == nil {
2016-11-03 22:14:27 +00:00
return conn
}
2017-04-27 09:37:25 +00:00
var reader Reader = NoOpReader{}
2017-04-13 20:17:58 +00:00
if a.config.Request != nil {
2016-11-05 00:50:51 +00:00
reader = new(HeaderReader)
}
2017-04-27 09:37:25 +00:00
var writer Writer = NoOpWriter{}
2017-04-13 20:17:58 +00:00
if a.config.Response != nil {
writer = a.GetClientWriter()
2016-11-05 00:50:51 +00:00
}
return NewConn(conn, reader, writer, NoOpWriter{}, NoOpWriter{}, NoOpWriter{})
2016-10-31 21:26:46 +00:00
}
func (a Authenticator) Server(conn net.Conn) net.Conn {
2017-04-13 20:17:58 +00:00
if a.config.Request == nil && a.config.Response == nil {
2016-11-03 22:14:27 +00:00
return conn
}
return NewConn(conn, new(HeaderReader).ExpectThisRequest(a.config.Request), a.GetServerWriter(),
formResponseHeader(resp400),
formResponseHeader(resp404),
formResponseHeader(resp400))
2016-10-31 21:26:46 +00:00
}
2016-10-31 23:42:55 +00:00
func NewAuthenticator(ctx context.Context, config *Config) (Authenticator, error) {
return Authenticator{
2017-01-13 12:47:44 +00:00
config: config,
2017-01-12 21:47:10 +00:00
}, nil
}
2016-10-31 23:42:55 +00:00
func init() {
2017-01-13 12:47:44 +00:00
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewAuthenticator(ctx, config.(*Config))
2017-01-13 12:47:44 +00:00
}))
2016-10-31 23:42:55 +00:00
}