Implement STDIOTunnel (#70)

This commit is contained in:
François Guerraz 2023-06-14 02:17:32 +00:00 committed by GitHub
parent edf63253df
commit aa207764b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 0 deletions

View file

@ -94,6 +94,16 @@ Target = play.cubecraft.net:25565
ListenPort = 3422
Target = localhost:25545
# STDIOTunnel is a tunnel connecting the standard input and output of the wireproxy
# process to the specified TCP target via wireguard.
# This is especially useful to use wireproxy as a ProxyCommand parameter in openssh
# For example:
# ssh -o ProxyCommand='wireproxy -c myconfig.conf' ssh.myserver.net
# Flow:
# Piped command -->(wireguard)--> ssh.myserver.net:22
[STDIOTunnel]
Target = ssh.myserver.net:22
# Socks5 creates a socks5 proxy on your LAN, and all traffic would be routed via wireguard.
[Socks5]
BindAddress = 127.0.0.1:25344

View file

@ -5,6 +5,7 @@ import (
"log"
"os"
"os/exec"
"syscall"
"github.com/akamensky/argparse"
"github.com/octeep/wireproxy"
@ -116,6 +117,10 @@ func main() {
return
}
// Wireguard doesn't allow configuring which FD to use for logging
// https://github.com/WireGuard/wireguard-go/blob/master/device/logger.go#L39
// so redirect STDOUT to STDERR, we don't want to print anything to STDOUT anyways
os.Stdout = os.NewFile(uintptr(syscall.Stderr), "/dev/stderr")
logLevel := device.LogLevelVerbose
if *silent {
logLevel = device.LogLevelSilent

View file

@ -34,6 +34,10 @@ type TCPClientTunnelConfig struct {
Target string
}
type STDIOTunnelConfig struct {
Target string
}
type TCPServerTunnelConfig struct {
ListenPort int
Target string
@ -300,6 +304,17 @@ func parseTCPClientTunnelConfig(section *ini.Section) (RoutineSpawner, error) {
return config, nil
}
func parseSTDIOTunnelConfig(section *ini.Section) (RoutineSpawner, error) {
config := &STDIOTunnelConfig{}
targetSection, err := parseString(section, "Target")
if err != nil {
return nil, err
}
config.Target = targetSection
return config, nil
}
func parseTCPServerTunnelConfig(section *ini.Section) (RoutineSpawner, error) {
config := &TCPServerTunnelConfig{}
@ -418,6 +433,11 @@ func ParseConfig(path string) (*Configuration, error) {
return nil, err
}
err = parseRoutinesConfig(&routinesSpawners, cfg, "STDIOTunnel", parseSTDIOTunnelConfig)
if err != nil {
return nil, err
}
err = parseRoutinesConfig(&routinesSpawners, cfg, "TCPServerTunnel", parseTCPServerTunnelConfig)
if err != nil {
return nil, err

View file

@ -192,6 +192,32 @@ func tcpClientForward(vt *VirtualTun, raddr *addressPort, conn net.Conn) {
go connForward(1024, conn, sconn)
}
// STDIOTcpForward starts a new connection via wireguard and forward traffic from `conn`
func STDIOTcpForward(vt *VirtualTun, raddr *addressPort) {
target, err := vt.resolveToAddrPort(raddr)
if err != nil {
errorLogger.Printf("Name resolution error for %s: %s\n", raddr.address, err.Error())
return
}
// os.Stdout has previously been remapped to stderr, se we can't use it
stdout, err := os.OpenFile("/dev/stdout", os.O_WRONLY, 0)
if err != nil {
errorLogger.Printf("Failed to open /dev/stdout: %s\n", err.Error())
return
}
tcpAddr := TCPAddrFromAddrPort(*target)
sconn, err := vt.Tnet.DialTCP(tcpAddr)
if err != nil {
errorLogger.Printf("TCP Client Tunnel to %s (%s): %s\n", target, tcpAddr, err.Error())
return
}
go connForward(1024, os.Stdin, sconn)
go connForward(1024, sconn, stdout)
}
// SpawnRoutine spawns a local TCP server which acts as a proxy to the specified target
func (conf *TCPClientTunnelConfig) SpawnRoutine(vt *VirtualTun) {
raddr, err := parseAddressPort(conf.Target)
@ -213,6 +239,16 @@ func (conf *TCPClientTunnelConfig) SpawnRoutine(vt *VirtualTun) {
}
}
// SpawnRoutine connects to the specified target and plumbs it to STDIN / STDOUT
func (conf *STDIOTunnelConfig) SpawnRoutine(vt *VirtualTun) {
raddr, err := parseAddressPort(conf.Target)
if err != nil {
log.Fatal(err)
}
go STDIOTcpForward(vt, raddr)
}
// tcpServerForward starts a new connection locally and forward traffic from `conn`
func tcpServerForward(vt *VirtualTun, raddr *addressPort, conn net.Conn) {
target, err := vt.resolveToAddrPort(raddr)