mirror of
https://github.com/amnezia-vpn/amneziawg-go.git
synced 2026-10-12 22:24:18 +03:00
207 lines
5.4 KiB
Go
207 lines
5.4 KiB
Go
package conn
|
|
|
|
import (
|
|
"net"
|
|
|
|
"github.com/amnezia-vpn/amneziawg-go/conceal"
|
|
)
|
|
|
|
type Framable interface {
|
|
SetFramedOpts(opts conceal.FramedOpts)
|
|
}
|
|
|
|
type Preludable interface {
|
|
SetPreludeOpts(opts conceal.PreludeOpts)
|
|
}
|
|
|
|
type Masqueradable interface {
|
|
SetMasqueradeOpts(opts conceal.MasqueradeOpts)
|
|
}
|
|
|
|
type Fallbackable interface {
|
|
SetFallbackPort(port uint16)
|
|
}
|
|
|
|
type concealStage string
|
|
|
|
const (
|
|
concealStageMasquerade concealStage = "masquerade"
|
|
concealStageRecord concealStage = "record"
|
|
concealStageFramed concealStage = "framed"
|
|
concealStagePrelude concealStage = "prelude"
|
|
)
|
|
|
|
type concealPipeline struct {
|
|
stages []concealStage
|
|
}
|
|
|
|
func (p concealPipeline) names() []string {
|
|
names := make([]string, 0, len(p.stages))
|
|
for _, stage := range p.stages {
|
|
names = append(names, string(stage))
|
|
}
|
|
return names
|
|
}
|
|
|
|
func hasFramed(opts conceal.FramedOpts) bool {
|
|
return opts.H1 != nil || opts.H2 != nil || opts.H3 != nil || opts.H4 != nil ||
|
|
opts.S1 != 0 || opts.S2 != 0 || opts.S3 != 0 || opts.S4 != 0
|
|
}
|
|
|
|
func hasMasquerade(opts conceal.MasqueradeOpts) bool {
|
|
return opts.RulesIn != nil || opts.RulesOut != nil
|
|
}
|
|
|
|
func hasBidirectionalStreamRecords(opts conceal.MasqueradeOpts) bool {
|
|
return opts.RulesIn != nil && opts.RulesOut != nil
|
|
}
|
|
|
|
func udpPreludeHeader(opts conceal.FramedOpts) *conceal.RangedHeader {
|
|
if opts.HeaderCompat {
|
|
return opts.H1
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func udpConcealPipeline(
|
|
framedOpts conceal.FramedOpts,
|
|
preludeOpts conceal.PreludeOpts,
|
|
masqueradeOpts conceal.MasqueradeOpts,
|
|
) concealPipeline {
|
|
stages := make([]concealStage, 0, 3)
|
|
if hasMasquerade(masqueradeOpts) {
|
|
stages = append(stages, concealStageMasquerade)
|
|
}
|
|
if hasFramed(framedOpts) {
|
|
stages = append(stages, concealStageFramed)
|
|
}
|
|
if !preludeOpts.IsEmpty() {
|
|
stages = append(stages, concealStagePrelude)
|
|
}
|
|
return concealPipeline{stages: stages}
|
|
}
|
|
|
|
func (b *StdNetBind) udpConcealPipeline() concealPipeline {
|
|
return udpConcealPipeline(b.framedOpts, b.preludeOpts, b.masqueradeOpts)
|
|
}
|
|
|
|
func (b *StdNetBind) batchConcealPipeline() concealPipeline {
|
|
return b.udpConcealPipeline()
|
|
}
|
|
|
|
func (b *BindStream) streamConcealPipeline() concealPipeline {
|
|
stages := make([]concealStage, 0, 3)
|
|
if hasMasquerade(b.masqueradeOpts) {
|
|
stages = append(stages, concealStageRecord)
|
|
}
|
|
if b.preludeOpts.HasDecoyRules() && hasBidirectionalStreamRecords(b.masqueradeOpts) {
|
|
stages = append(stages, concealStagePrelude)
|
|
}
|
|
if hasFramed(b.framedOpts) {
|
|
stages = append(stages, concealStageFramed)
|
|
}
|
|
return concealPipeline{stages: stages}
|
|
}
|
|
|
|
func (b *StdNetBind) upgradeUDPConn(conn UDPConn) UDPConn {
|
|
origin := conn
|
|
for _, stage := range b.udpConcealPipeline().stages {
|
|
switch stage {
|
|
case concealStageMasquerade:
|
|
if masquerade, ok := conceal.NewMasqueradeUDPConn(conn, &b.bufPool, b.masqueradeOpts); ok {
|
|
conn = masquerade
|
|
}
|
|
case concealStageFramed:
|
|
if framed, ok := conceal.NewFramedUDPConn(conn, &b.bufPool, b.framedOpts); ok {
|
|
conn = framed
|
|
}
|
|
case concealStagePrelude:
|
|
if prelude, ok := conceal.NewPreludeUDPConn(conn, origin, &b.bufPool, udpPreludeHeader(b.framedOpts), b.preludeOpts); ok {
|
|
conn = prelude
|
|
}
|
|
}
|
|
}
|
|
if b.fallbackPort != 0 {
|
|
conn = newFallbackUDPConn(conn, origin, b.fallbackPort)
|
|
}
|
|
return conn
|
|
}
|
|
|
|
func (b *StdNetBind) upgradePacketConn(conn LinuxPacketConn) LinuxPacketConn {
|
|
origin := conn
|
|
for _, stage := range b.batchConcealPipeline().stages {
|
|
switch stage {
|
|
case concealStageMasquerade:
|
|
if masquerade, ok := conceal.NewMasqueradeBatchConn(conn, &b.bufPool, b.masqueradeOpts); ok {
|
|
conn = masquerade
|
|
}
|
|
case concealStageFramed:
|
|
if framed, ok := conceal.NewFramedBatchConn(conn, &b.bufPool, b.framedOpts); ok {
|
|
conn = framed
|
|
}
|
|
case concealStagePrelude:
|
|
if prelude, ok := conceal.NewPreludeBatchConn(conn, origin, &b.bufPool, &b.msgsPool, udpPreludeHeader(b.framedOpts), b.preludeOpts); ok {
|
|
conn = prelude
|
|
}
|
|
}
|
|
}
|
|
if b.fallbackPort != 0 {
|
|
conn = newFallbackBatchConn(conn, origin, b.fallbackPort)
|
|
}
|
|
return conn
|
|
}
|
|
|
|
func (b *StdNetBind) SetFramedOpts(opts conceal.FramedOpts) {
|
|
b.framedOpts = opts
|
|
}
|
|
|
|
func (b *StdNetBind) SetPreludeOpts(opts conceal.PreludeOpts) {
|
|
b.preludeOpts = opts
|
|
}
|
|
|
|
func (b *StdNetBind) SetMasqueradeOpts(opts conceal.MasqueradeOpts) {
|
|
b.masqueradeOpts = opts
|
|
}
|
|
|
|
func (b *StdNetBind) SetFallbackPort(port uint16) {
|
|
b.fallbackPort = port
|
|
}
|
|
|
|
func (b *BindStream) upgradeConn(conn net.Conn, preludeState *conceal.PreludeState, emitPrelude bool) net.Conn {
|
|
var recordConn conceal.StreamRecordConn
|
|
for _, stage := range b.streamConcealPipeline().stages {
|
|
switch stage {
|
|
case concealStageRecord:
|
|
if masquerade, ok := conceal.NewMasqueradeConn(conn, &b.bufferPool, b.masqueradeOpts); ok {
|
|
recordConn = masquerade
|
|
conn = masquerade
|
|
}
|
|
case concealStagePrelude:
|
|
if prelude, ok := conceal.NewPreludeConnWithState(recordConn, &b.bufferPool, b.framedOpts, b.preludeOpts, preludeState, emitPrelude); ok {
|
|
conn = prelude
|
|
}
|
|
case concealStageFramed:
|
|
if framed, ok := conceal.NewFramedConn(conn, &b.bufferPool, b.framedOpts); ok {
|
|
conn = framed
|
|
}
|
|
}
|
|
}
|
|
return conn
|
|
}
|
|
|
|
func (b *BindStream) SetFramedOpts(opts conceal.FramedOpts) {
|
|
b.framedOpts = opts
|
|
}
|
|
|
|
func (b *BindStream) SetPreludeOpts(opts conceal.PreludeOpts) {
|
|
b.preludeOpts = opts
|
|
}
|
|
|
|
func (b *BindStream) SetMasqueradeOpts(opts conceal.MasqueradeOpts) {
|
|
b.masqueradeOpts = opts
|
|
}
|
|
|
|
func (b *BindStream) SetFallbackPort(port uint16) {
|
|
b.fallbackPort = port
|
|
}
|