mirror of https://github.com/docker/docs.git
Emulate DNAT in userland for loopback-to-loopback connections. This makes container ports available from localhost.
This commit is contained in:
parent
61259ab4b4
commit
930e9a7e43
46
network.go
46
network.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -221,10 +222,55 @@ func (mapper *PortMapper) Map(port int, dest net.TCPAddr) error {
|
||||||
if err := mapper.iptablesForward("-A", port, dest); err != nil {
|
if err := mapper.iptablesForward("-A", port, dest); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mapper.mapping[port] = dest
|
mapper.mapping[port] = dest
|
||||||
|
listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
|
||||||
|
if err != nil {
|
||||||
|
mapper.Unmap(port)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// FIXME: store the listener so we can close it at Unmap
|
||||||
|
go proxy(listener, "tcp", dest.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// proxy listens for socket connections on `listener`, and forwards them unmodified
|
||||||
|
// to `proto:address`
|
||||||
|
func proxy(listener net.Listener, proto, address string) error {
|
||||||
|
Debugf("proxying to %s:%s", proto, address)
|
||||||
|
defer Debugf("Done proxying to %s:%s", proto, address)
|
||||||
|
for {
|
||||||
|
Debugf("Listening on %s", listener)
|
||||||
|
src, err := listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
Debugf("Connecting to %s:%s", proto, address)
|
||||||
|
dst, err := net.Dial(proto, address)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error connecting to %s:%s: %s", proto, address, err)
|
||||||
|
src.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
Debugf("Connected to backend, splicing")
|
||||||
|
splice(src, dst)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func halfSplice(dst, src net.Conn) error {
|
||||||
|
_, err := io.Copy(dst, src)
|
||||||
|
// FIXME: on EOF from a tcp connection, pass WriteClose()
|
||||||
|
dst.Close()
|
||||||
|
src.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func splice(a, b net.Conn) {
|
||||||
|
go halfSplice(a, b)
|
||||||
|
go halfSplice(b, a)
|
||||||
|
}
|
||||||
|
|
||||||
func (mapper *PortMapper) Unmap(port int) error {
|
func (mapper *PortMapper) Unmap(port int) error {
|
||||||
dest, ok := mapper.mapping[port]
|
dest, ok := mapper.mapping[port]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
Loading…
Reference in New Issue