forwarder.go 3.3 KB

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