http.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package http
  2. import (
  3. "bufio"
  4. "net"
  5. "net/http"
  6. "strconv"
  7. "strings"
  8. "github.com/v2ray/v2ray-core/app"
  9. "github.com/v2ray/v2ray-core/common/alloc"
  10. "github.com/v2ray/v2ray-core/common/log"
  11. v2net "github.com/v2ray/v2ray-core/common/net"
  12. )
  13. type HttpProxyServer struct {
  14. accepting bool
  15. space app.Space
  16. config Config
  17. }
  18. func NewHttpProxyServer(space app.Space, config Config) *HttpProxyServer {
  19. return &HttpProxyServer{
  20. space: space,
  21. config: config,
  22. }
  23. }
  24. func (this *HttpProxyServer) Listen(port v2net.Port) error {
  25. tcpListener, err := net.ListenTCP("tcp", &net.TCPAddr{
  26. Port: int(port.Value()),
  27. IP: []byte{0, 0, 0, 0},
  28. })
  29. if err != nil {
  30. return err
  31. }
  32. go this.accept(tcpListener)
  33. return nil
  34. }
  35. func (this *HttpProxyServer) accept(listener *net.TCPListener) {
  36. this.accepting = true
  37. for this.accepting {
  38. tcpConn, err := listener.AcceptTCP()
  39. if err != nil {
  40. log.Error("Failed to accept HTTP connection: %v", err)
  41. continue
  42. }
  43. go this.handleConnection(tcpConn)
  44. }
  45. }
  46. func parseHost(rawHost string) (v2net.Address, error) {
  47. port := v2net.Port(80)
  48. host, rawPort, err := net.SplitHostPort(rawHost)
  49. if err != nil {
  50. if addrError, ok := err.(*net.AddrError); ok && strings.Contains(addrError.Err, "missing port") {
  51. host = rawHost
  52. port = v2net.Port(80)
  53. } else {
  54. return nil, err
  55. }
  56. }
  57. intPort, err := strconv.Atoi(rawPort)
  58. if err != nil {
  59. return nil, err
  60. }
  61. port = v2net.Port(intPort)
  62. if ip := net.ParseIP(host); ip != nil {
  63. return v2net.IPAddress(ip, port), nil
  64. }
  65. return v2net.DomainAddress(host, port), nil
  66. }
  67. func (this *HttpProxyServer) handleConnection(conn *net.TCPConn) {
  68. httpReader := bufio.NewReader(conn)
  69. request, err := http.ReadRequest(httpReader)
  70. if err != nil {
  71. log.Warning("Malformed HTTP request: %v", err)
  72. return
  73. }
  74. if strings.ToUpper(request.Method) == "CONNECT" {
  75. address, err := parseHost(request.Host)
  76. if err != nil {
  77. log.Warning("Malformed proxy host: %v", err)
  78. return
  79. }
  80. response := &http.Response{
  81. Status: "200 OK",
  82. StatusCode: 200,
  83. Proto: "HTTP/1.1",
  84. ProtoMajor: 1,
  85. ProtoMinor: 1,
  86. Header: http.Header(make(map[string][]string)),
  87. Body: nil,
  88. ContentLength: 0,
  89. Close: false,
  90. }
  91. buffer := alloc.NewSmallBuffer().Clear()
  92. response.Write(buffer)
  93. conn.Write(buffer.Value)
  94. packet := v2net.NewPacket(v2net.NewTCPDestination(address), nil, true)
  95. this.space.PacketDispatcher().DispatchToOutbound(packet)
  96. }
  97. }