nxproxy

package module
v0.1.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2025 License: MIT Imports: 18 Imported by: 0

README

Elevator pitch

NX is a spin-off of VX that used proxying-tables over REST instead of RADIUS protocol.

Proxy protocols

SOCKS 5

Features:

  • ✅ CONNECT command
  • ⏳ BIND command
  • ⏳ ASSOCIATE command
  • ⏳ UDP proxy
  • ✅ IPv4/IPV6/DOMAIN address type support
  • ✅ Password auth
HTTP

Features:

  • ✅ HTTP tunnelling
  • ✅ Forward-proxying
  • ✅ Basic proxy auth (username/password)

Installing

A binary Debian package is available in Releases.

Building from source is also possible at any point. I mean, it's just a go package after all.

To avoid having to mess with network addresses in docker it's recommended to install NX directly to a host system.

Configuration

Since the whole point of this thing is to avoid having to manually configure instances - all the service options are provided via the API.

In order to authenticate an instance against your backend you must pass AUTH_URL and SECRET_TOKEN to one of the config locations, such as /etc/nx-proxy/nx-proxy.conf.

A sample config file would look like this:

SECRET_TOKEN=<YOUR_BASE64_ENCODED_TOKEN_HERE>
AUTH_URL=<YOUR_BACKEND_URL_AND_PATH_PREFIX>
# optional debug flag
# WARNING: it causes the logs to be pretty flooded!
# DEBUG=true

Important note: URL's support path prefixes. For instance, if your auth endpoint is located at https://backend.myapp.local/api/rest/v1/proxytables/ - this is exactly what your AUTH_URL should look like. All the necessary paths would be appended to this base url.

Documentation

Index

Constants

View Source
const (
	ProxyProtoSocks = ProxyProto("socks")
	ProxyProtoHttp  = ProxyProto("http")
)

Variables

View Source
var DefaultRatelimiter = RateLimiterOptions{
	Quota:  50,
	Window: 5 * time.Minute,
}
View Source
var ErrSlotOptionsIncompatible = errors.New("slot options incompatible")
View Source
var ErrTooManyConnections = errors.New("too many connections")
View Source
var ErrUnsupportedProto = errors.New("unsupported protocol")

Functions

func AddrAssigned

func AddrAssigned(addr net.IP) (bool, error)

func DurationTCIO

func DurationTCIO(bandwidth int, size int) time.Duration

Returns the amount of time it's expected for an IO operation to take. Bandwidth in bps, size in bytes

func GetAddrPort

func GetAddrPort(addr net.Addr) (net.IP, int)

func IsLocalAddress

func IsLocalAddress(addr string) bool

func NewDnsResolver

func NewDnsResolver(addr string) (*net.Resolver, error)

func ParseFramedIP

func ParseFramedIP(addr string) (net.IP, error)

func ProbeDnsServer

func ProbeDnsServer(addr string) error

func ProxyBridge

func ProxyBridge(ctl *PeerConnection, clientConn net.Conn, remoteConn net.Conn) (err error)

Bridges two connections together to create a proxy

func ReadByte

func ReadByte(reader io.Reader) (byte, error)

func ReadN

func ReadN(reader io.Reader, n int) ([]byte, error)

func RedistributePeerBandwidth

func RedistributePeerBandwidth(conns []*PeerConnection, bandwidth PeerBandwidth)

func ServiceBindAddr

func ServiceBindAddr(addr string, service ProxyProto) (string, error)

func SpliceConn

func SpliceConn(ctx context.Context, dst io.Writer, src io.Reader, bw BandwidthFn, acct AccountFn) error

Forwards data from src to dst while limiting data rate and accounting for traffic volume

func SplitAddrNet

func SplitAddrNet(addr string) (string, string, bool)

func TcpDialAddr

func TcpDialAddr(addr net.IP) net.Addr

func WaitTCIO

func WaitTCIO(bandwidth int, size int, started time.Time)

Creates a fake delay that can be used to limit data transfer rate

Types

type AccountFn

type AccountFn func(delta int)

type AddrContainer

type AddrContainer interface {
	Contains(val net.IP) bool
}

type BandwidthFn

type BandwidthFn func() (int, bool)

Implementations of BandwidthFn must return the data volume in bytes that a connection may copy in one second at most

type CredentialsError

type CredentialsError struct {
	Username *string
}

func (*CredentialsError) Error

func (err *CredentialsError) Error() string

type DnsProvider

type DnsProvider interface {
	Resolver() *net.Resolver
}

type Peer

type Peer struct {
	PeerOptions

	BaseContext context.Context
	Dialer      net.Dialer
	HttpClient  *http.Client

	DeltaRx atomic.Uint64
	DeltaTx atomic.Uint64
	// contains filtered or unexported fields
}

func (*Peer) CloseConnections

func (peer *Peer) CloseConnections()

func (*Peer) Connection

func (peer *Peer) Connection() (*PeerConnection, error)

func (*Peer) ConnectionList

func (peer *Peer) ConnectionList() []*PeerConnection

func (*Peer) Delta

func (peer *Peer) Delta() (PeerDelta, bool)

type PeerBandwidth

type PeerBandwidth struct {

	//	total connection bandwidth for up/down streams
	Rx uint32 `json:"rx"`
	Tx uint32 `json:"tx"`

	//	respective minimal speed per connection
	MinRx uint32 `json:"min_rx"`
	MinTx uint32 `json:"min_tx"`
}

type PeerConnection

type PeerConnection struct {
	// contains filtered or unexported fields
}

func (*PeerConnection) AccountRx

func (conn *PeerConnection) AccountRx(delta int)

func (*PeerConnection) AccountTx

func (conn *PeerConnection) AccountTx(delta int)

func (*PeerConnection) BandwidthRx

func (conn *PeerConnection) BandwidthRx() (int, bool)

func (*PeerConnection) BandwidthTx

func (conn *PeerConnection) BandwidthTx() (int, bool)

func (*PeerConnection) Close

func (conn *PeerConnection) Close()

func (*PeerConnection) Context

func (conn *PeerConnection) Context() context.Context

type PeerDelta

type PeerDelta struct {

	//	unique peer ID
	ID uuid.UUID `json:"id"`

	//	data transferred
	Rx uint64 `json:"rx"`
	Tx uint64 `json:"tx"`
}

type PeerOptions

type PeerOptions struct {

	//	unique peer ID used for accounting identification
	ID uuid.UUID `json:"id"`

	//	optional (not so) paasword auth data
	PasswordAuth *UserPassword `json:"password_auth"`

	//	maximal number of open connections
	MaxConnections uint `json:"max_connections"`

	//	connection speed limits
	Bandwidth PeerBandwidth `json:"bandwidth"`

	//	public ip to use for outbound connections, optional
	FramedIP string `json:"framed_ip,omitempty"`

	//	used to disable a peer without completely removing it
	Disabled bool `json:"disabled"`
}

func (*PeerOptions) CmpCredentials

func (peer *PeerOptions) CmpCredentials(other PeerOptions) bool

func (*PeerOptions) DisplayName

func (peer *PeerOptions) DisplayName() string

type ProxyProto

type ProxyProto string

func (ProxyProto) Valid

func (val ProxyProto) Valid() bool

type RateLimitError

type RateLimitError struct {
	Expires time.Time
}

func (*RateLimitError) Error

func (val *RateLimitError) Error() string

type RateLimiter

type RateLimiter struct {
	RateLimiterOptions
	// contains filtered or unexported fields
}

func (*RateLimiter) Get

func (rl *RateLimiter) Get(key string) *RlCounter

type RateLimiterOptions

type RateLimiterOptions struct {
	Quota  int64
	Window time.Duration
}

type RlCounter

type RlCounter struct {
	// contains filtered or unexported fields
}

func (*RlCounter) Reset

func (rlc *RlCounter) Reset()

func (*RlCounter) Use

func (rlc *RlCounter) Use() error

type ServerToken

type ServerToken struct {
	ID        uuid.UUID
	SecretKey []byte
}

func NewServerToken

func NewServerToken() (*ServerToken, error)

func ParseServerToken

func ParseServerToken(val string) (*ServerToken, error)

func (*ServerToken) String

func (token *ServerToken) String() string

type ServiceOptions

type ServiceOptions struct {
	SlotOptions
	Peers []PeerOptions `json:"peers"`
}

type Slot

type Slot struct {
	SlotOptions

	BaseContext context.Context
	Rl          *RateLimiter
	DNS         DnsProvider
	// contains filtered or unexported fields
}

func (*Slot) ClosePeerConnections

func (slot *Slot) ClosePeerConnections()

func (*Slot) Deltas

func (slot *Slot) Deltas() []PeerDelta

func (*Slot) Info

func (slot *Slot) Info() SlotInfo

func (*Slot) LookupWithPassword

func (slot *Slot) LookupWithPassword(ip net.IP, username, password string) (*Peer, error)

func (*Slot) SetPeers

func (slot *Slot) SetPeers(entries []PeerOptions)

type SlotInfo

type SlotInfo struct {
	Up              bool       `json:"up"`
	Proto           ProxyProto `json:"proto"`
	BindAddr        string     `json:"bind_addr"`
	RegisteredPeers int        `json:"registered_peers"`
	Error           string     `json:"error,omitempty"`
}

type SlotOptions

type SlotOptions struct {
	Proto    ProxyProto `json:"proto"`
	BindAddr string     `json:"bind_addr"`
}

func (*SlotOptions) Compatible added in v0.1.2

func (opts *SlotOptions) Compatible(other *SlotOptions) bool

type SlotService

type SlotService interface {
	Info() SlotInfo
	Deltas() []PeerDelta
	SetPeers(entries []PeerOptions)
	SetOptions(opts SlotOptions) error
	Close() error
}

type UserPassword

type UserPassword struct {
	User     string `json:"user"`
	Password string `json:"password"`
}

Directories

Path Synopsis
testing
cmd/nx-auth command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL