Code Monkey home page Code Monkey logo

websocketproxy's Introduction

websocket proxy

License GitHub go.mod Go version

Lightweight websocket proxy library

100 lines of code implements a lightweight websocket proxy library, does not depend on other third-party libraries, and supports ws and wss proxies; if you only need a simple websocket traffic proxy function without any modification to the forwarded content, using this library will be very useful.

Content

Features

  • Extreme performance, almost no performance loss, very low consumption of cpu and memory
  • Support websocket handshake phase for management and control
  • Supports setting header headers (cookie, origin, etc.) in the handshake phase
  • Support ws, wss proxy

Install

go get github.com/pretty66/websocketproxy

Use

import (
    "github.com/pretty66/websocketproxy"
    "net/http"
)

wp, err := websocketproxy.NewProxy("ws://82.157.123.54:9010/ajaxchattest", func(r *http.Request) error {
    // Permission to verify
    r.Header.Set("Cookie", "----")
    // Source of disguise
    r.Header.Set("Origin", "http://82.157.123.54:9010")
    return nil
})
if err != nil {
    t.Fatal()
}
// proxy path
http.HandleFunc("/wsproxy", wp.Proxy)
http.ListenAndServe(":9696", nil)

Test

Run the test file and start listening on the 127.0.0.1:9696 port, and use the online testing tool http://coolaf.com/tool/chattest to connect to the proxy to test the request response

example

example

Core-code

func (wp *WebsocketProxy) Proxy(writer http.ResponseWriter, request *http.Request) {
    // Check whether it is a Websocket request
	if strings.ToLower(request.Header.Get("Connection")) != "upgrade" ||
		strings.ToLower(request.Header.Get("Upgrade")) != "websocket" {
		_, _ = writer.Write([]byte(`Must be a websocket request`))
		return
	}
    // Hijack connections
	hijacker, ok := writer.(http.Hijacker)
	if !ok {
		return
	}
	conn, _, err := hijacker.Hijack()
	if err != nil {
		return
	}
	defer conn.Close()
    // Clone request, set destination address path
	req := request.Clone(context.TODO())
	req.URL.Path, req.URL.RawPath, req.RequestURI = wp.defaultPath, wp.defaultPath, wp.defaultPath
	req.Host = wp.remoteAddr
    // Handshake before callback
	if wp.beforeHandshake != nil {
		// Add headers, permission authentication + masquerade sources
		err = wp.beforeHandshake(req)
		if err != nil {
			_, _ = writer.Write([]byte(err.Error()))
			return
		}
	}
    // Determine the protocol and select the dialing process
	var remoteConn net.Conn
	switch wp.scheme {
	case WsScheme:
		remoteConn, err = net.Dial("tcp", wp.remoteAddr)
	case WssScheme:
		remoteConn, err = tls.Dial("tcp", wp.remoteAddr, wp.tlsc)
	}
	if err != nil {
		_, _ = writer.Write([]byte(err.Error()))
		return
	}
	defer remoteConn.Close()
	// Sends a handshake packet to the target WebSocket service
	err = req.Write(remoteConn)
	if err != nil {
		wp.logger.Println("remote write err:", err)
		return
	}
    // Traffic transparent transmission
	errChan := make(chan error, 2)
	copyConn := func(a, b net.Conn) {
		_, err := io.Copy(a, b)
		errChan <- err
	}
	go copyConn(conn, remoteConn) // response
	go copyConn(remoteConn, conn) // request
	select {
	case err = <-errChan:
		if err != nil {
			log.Println(err)
		}
	}
}

Thanks for free JetBrains Open Source license

License

websocketproxy is under the Apache 2.0 license. See the LICENSE directory for details.

websocketproxy's People

Contributors

pretty66 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

websocketproxy's Issues

Firefox Headers

Hi there!

First off, thank you so much for your work here! I'm glad I was able to find it when I needed exactly what the package offers.

While building a project using it, I came across this behavior where Firefox isn't working as expected, while all Chromium-based browsers just work fine. After debugging, I realized that the issue lies in the function Proxy, as it expects the header 'Connection' to be 'Upgrade'. However, with Firefox, when connecting to a websocket, it uses the header 'keep-alive, Upgrade' instead, and that's what was causing the issue and kept returning without giving any errors.

I'd be more than happy to make a PR if you're okay with that. Just let me know!

将【pretty66 / websocketproxy】和Beego2.0链接起来使用

1、我用的golang1.15.6版本在72行代码提示【logger: log.Default(),】没找到log.Default函数,直接删除改行代码即可。
2、将源代码中的【Proxy】函数名称,修改为【ServeHTTP】。
3、在Beego侧的注入方式是:
wp, err := websocketproxy.NewProxy("ws://localhost:1884/mqtt", func(r *http.Request) error {
// 权限验证
r.Header.Set("Cookie", "----")
// 伪装来源
r.Header.Set("Origin", "http://82.157.123.54:9010")
return nil
})
if err != nil {
logs.GetLogger().Println(err)
os.Exit(999)
}
web.Handler("/wsproxy", wp)

Mqtt服务器使用的是Mosquitto1.6.12 for windows64bit。
希望对后来的Beego同学能够有点帮助。

请教下,如何集成到现有的gorilla项目里?

您好
我有个gorilla聊天的项目,这个项目是基于ws协议的,我想把ws协议的数据进行加密变成wss协议。我可不可以直接把您的代码集成到我的代码里,把gorilla的聊天项目变成wss协议(通过ssl证书加密)?

请教下两个关于性能的问题

1.把这个开发项目的API集成到自己的go开发项目里,相比用nginx进行wss的代理,性能上有什么优势?
2.我看到proxy.go里面使用了net/http的包,如果用fasthttp,是不是性能会更好一点。不知道当前的项目有没有基于fasthttp的版本?
谢谢啦。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.