Giter Site home page Giter Site logo

masque-go's Introduction

masque-go

PkgGoDev Code Coverage

masque-go is an implementation of the CONNECT-UDP protocol RFC 9298, based on quic-go.

masque-go's People

Contributors

marten-seemann 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

Watchers

 avatar  avatar  avatar

Forkers

explse

masque-go's Issues

allow applications to control DNS resolution

A proxy might want to control DNS resolution of target hosts (e.g. force usage of DoH). This is currently not possible, since the proxy implementation handles DNS resolution.

We could combine pass the hostname to DialTarget instead:

type Proxy struct {
	// DialTarget is called when the proxy needs to open a new UDP socket to the target server.
	// It must return a connected UDP socket.
	// TODO(#3): support unconnected sockets.
	DialTarget func(context.Context, string) (*net.UDPConn, error)
}

This would also allow us to remove the Allow callback.

It's not clear how we should set the HTTP status code though.

application-defined handlers don't make sense

The URL should is already encoded in the URI template. Unfortunately, it doesn't seem like the URI template library allows us to extract it though, so we might need to jump through some hoops to obtain it.

use GSO to send packets to the target

This will likely improve performance on high-bandwidth connections.

We should probably refactor quite a bit of quic-go's GSO code into a separate package (repo?), so we don't have to build all the platform-specific code again.

MTU settings prevent tunnelling of QUIC

quic-go currently uses a hard-coded initial MTU. This means that we currently can't proxy QUIC traffic, since the MTU of the outer and the inner connection are the same, and therefore the DATAGRAM frames don't fit into the QUIC packets.

alternative request handling API

There are a number of issues highlighting deficiencies with the current proxy API: #3, #4, #13, #41. There's a lot of back-and-forth between the request handler and the application, if we want to enable the fine-grained access control that's table stakes for a production-ready proxy.

The reason that implementing a HTTP CONNECT proxy is so much easier is because the http.Request contains all fields that are needed to make the proxying decison.

We could replicate this by implementing a ParseRequest function on the Proxy:

type Proxy struct {
     // Template is the URI template that clients will use to configure this UDP proxy.
     Template *uritemplate.Template
}

func (p *Proxy) ParseRequest(*http.Request) (*Request, error) {
     // parse the request using the configure URI template
}

Borrowing the idea from #41 (comment), the returned error could implement a ParseError, allowing the application to set the correct HTTP status code (while also allowing it to ignore the suggestion and set their own status):

type ParsingError struct {
    HTTPStatus int
    Error string
}

func (e *ParsingError) Error() string { return e.Error }

After ParseRequest, it's the application's responsibility to decide how to proceed with the request. In case it wishes to continue, it needs to pass the masque.Request back to the Proxy, together with a connection to the target host:

func (p *Proxy) HandleRequest(*Request, *net.UDPConn) error {
    // proxy packets back and forth
}

set the DF bit

A proxy MUST NOT introduce fragmentation at the IP layer.

connected and unconnected sockets

Currently the proxy uses connected sockets. This is a good idea performance-wise, but comes with the obvious limitation on the number of proxied connections.

We should have an API that allows an application more fine-grained control. One option would be a callback on the Server:

type Server struct {
    // ... existing stuff
    
    // PacketConnForRemote is called when establishing a new proxied connection.
    // It is possible to return the same net.PacketConn (an unconnected UDP socket) for multiple distinct remote address.
    // However, the same net.PacketConn cannot be used for the same remote address.
    PacketConnForRemote(*net.UDPAddr) net.PacketConn
}

The problem here is that the same net.PacketConn can't be used for the same remote address: We need to know which QUIC connection to put a packet on. It's also not clear how timeouts should work: If one proxied connection is closed, it should be possible to reuse the same net.PacketConn at some point, but probably not immediately, since UDP packets might still be in flight between the remote and the proxy.

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.