Last active
April 15, 2020 23:01
-
-
Save mathershifter/8f9df10e5128263bf98d38dd37418578 to your computer and use it in GitHub Desktop.
Experimenting with sockets in a namespace
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// +build go1.10 | |
// Demo listening on a socket inside an network namespace | |
package main | |
import ( | |
"bufio" | |
"fmt" | |
"net" | |
"runtime" | |
"github.com/vishvananda/netns" | |
) | |
const nsname string = "ns-management" | |
// Message to pass | |
type Message struct { | |
text string | |
conn net.Conn | |
} | |
func main() { | |
origns, err := netns.Get() | |
panicOnErr(err) | |
fmt.Println("Parent NS:", origns) | |
messages := make(chan Message) | |
go func() { | |
err := withNetNS(nsname, func() error { | |
ns, err := netns.Get() | |
if err != nil { | |
return err | |
} | |
fmt.Println("Server NS:", ns) | |
ln, err := net.Listen("tcp", ":50001") | |
for { | |
conn, err := ln.Accept() | |
if err != nil { | |
return err | |
} | |
go func() { | |
buf := bufio.NewReader(conn) | |
for { | |
text, err := buf.ReadString('\n') | |
if err != nil { | |
fmt.Println("client went away. :(") | |
break | |
} | |
messages <- Message{text, conn} | |
} | |
}() | |
} | |
}) | |
panicOnErr(err) | |
}() | |
for { | |
// Wait for the next message | |
message := <-messages | |
currentns, err := netns.Get() | |
panicOnErr(err) | |
fmt.Println("Current NS:", currentns) | |
fmt.Print(message.text) | |
message.conn.Write([]byte("Received: " + message.text)) | |
} | |
} | |
func panicOnErr(err error) { | |
if err != nil { | |
panic(err) | |
} | |
} | |
func withNetNS(nsname string, work func() error) error { | |
runtime.LockOSThread() | |
defer runtime.UnlockOSThread() | |
oldNs, err := netns.Get() | |
panicOnErr(err) | |
if err == nil { | |
defer oldNs.Close() | |
ns, err := netns.GetFromName(nsname) | |
panicOnErr(err) | |
err = netns.Set(ns) | |
panicOnErr(err) | |
if err == nil { | |
defer netns.Set(oldNs) | |
err = work() | |
} | |
} | |
return err | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment