forwarder.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // +build !confonly
  2. package browserforwarder
  3. import (
  4. "bytes"
  5. "context"
  6. "io"
  7. "net/http"
  8. "time"
  9. "github.com/v2fly/v2ray-core/v4/features/extension"
  10. "github.com/v2fly/BrowserBridge/handler"
  11. "github.com/v2fly/v2ray-core/v4/common"
  12. "github.com/v2fly/v2ray-core/v4/common/net"
  13. "github.com/v2fly/v2ray-core/v4/common/platform/securedload"
  14. "github.com/v2fly/v2ray-core/v4/transport/internet"
  15. )
  16. //go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
  17. type Forwarder struct {
  18. ctx context.Context
  19. forwarder *handler.HTTPHandle
  20. httpserver *http.Server
  21. config *Config
  22. }
  23. func (f *Forwarder) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
  24. requestPath := request.URL.Path[1:]
  25. switch requestPath {
  26. case "":
  27. fallthrough
  28. case "index.js":
  29. BridgeResource(writer, request, requestPath)
  30. case "link":
  31. f.forwarder.ServeBridge(writer, request)
  32. }
  33. }
  34. func (f *Forwarder) DialWebsocket(url string, header http.Header) (io.ReadWriteCloser, error) {
  35. protocolHeader := false
  36. protocolHeaderValue := ""
  37. unsupportedHeader := false
  38. for k, v := range header {
  39. if k == "Sec-Websocket-Protocol" {
  40. protocolHeader = true
  41. protocolHeaderValue = v[0]
  42. } else {
  43. unsupportedHeader = true
  44. }
  45. }
  46. if unsupportedHeader {
  47. return nil, newError("unsupported header used, only Sec-WebSocket-Protocol is supported for forwarder")
  48. }
  49. if !protocolHeader {
  50. return f.forwarder.Dial(url)
  51. }
  52. return f.forwarder.Dial2(url, protocolHeaderValue)
  53. }
  54. func (f *Forwarder) Type() interface{} {
  55. return extension.BrowserForwarderType()
  56. }
  57. func (f *Forwarder) Start() error {
  58. f.forwarder = handler.NewHttpHandle()
  59. f.httpserver = &http.Server{Handler: f}
  60. address := net.ParseAddress(f.config.ListenAddr)
  61. listener, err := internet.ListenSystem(f.ctx, &net.TCPAddr{IP: address.IP(), Port: int(f.config.ListenPort)}, nil)
  62. if err != nil {
  63. return newError("forwarder cannot listen on the port").Base(err)
  64. }
  65. go func() {
  66. err = f.httpserver.Serve(listener)
  67. if err != nil {
  68. newError("cannot serve http forward server").Base(err).WriteToLog()
  69. }
  70. }()
  71. return nil
  72. }
  73. func (f *Forwarder) Close() error {
  74. if f.httpserver != nil {
  75. return f.httpserver.Close()
  76. }
  77. return nil
  78. }
  79. func BridgeResource(rw http.ResponseWriter, r *http.Request, path string) {
  80. content := path
  81. if content == "" {
  82. content = "index.html"
  83. }
  84. data, err := securedload.GetAssetSecured("browserforwarder/" + content)
  85. if err != nil {
  86. err = newError("cannot load necessary resources").Base(err)
  87. http.Error(rw, err.Error(), http.StatusForbidden)
  88. return
  89. }
  90. http.ServeContent(rw, r, path, time.Now(), bytes.NewReader(data))
  91. }
  92. func NewForwarder(ctx context.Context, cfg *Config) *Forwarder {
  93. return &Forwarder{config: cfg, ctx: ctx}
  94. }
  95. func init() {
  96. common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
  97. return NewForwarder(ctx, cfg.(*Config)), nil
  98. }))
  99. }