mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-23 19:05:37 +00:00
Merge pull request #268 from djs55/iptables-for-master
Add the piñata-ga iptables wrapper
This commit is contained in:
commit
45309f136d
@ -75,6 +75,7 @@ COPY packages/9pmount-vsock/9pmount-vsock /sbin
|
|||||||
COPY packages/test/etc /etc
|
COPY packages/test/etc /etc
|
||||||
COPY packages/test/mobytest /usr/bin
|
COPY packages/test/mobytest /usr/bin
|
||||||
COPY packages/sysctl/etc /etc
|
COPY packages/sysctl/etc /etc
|
||||||
|
COPY packages/iptables/iptables /usr/local/sbin/iptables
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
rc-update add swap boot && \
|
rc-update add swap boot && \
|
||||||
|
@ -10,6 +10,7 @@ all:
|
|||||||
$(MAKE) -C llmnrd OS=linux
|
$(MAKE) -C llmnrd OS=linux
|
||||||
$(MAKE) -C gummiboot OS=linux
|
$(MAKE) -C gummiboot OS=linux
|
||||||
$(MAKE) -C 9pmount-vsock OS=linux
|
$(MAKE) -C 9pmount-vsock OS=linux
|
||||||
|
$(MAKE) -C iptables OS=linux
|
||||||
|
|
||||||
arm:
|
arm:
|
||||||
$(MAKE) -C transfused OS=linux ARCH=arm
|
$(MAKE) -C transfused OS=linux ARCH=arm
|
||||||
@ -33,3 +34,4 @@ clean:
|
|||||||
$(MAKE) -C llmnrd clean
|
$(MAKE) -C llmnrd clean
|
||||||
$(MAKE) -C gummiboot clean
|
$(MAKE) -C gummiboot clean
|
||||||
$(MAKE) -C 9pmount-vsock clean
|
$(MAKE) -C 9pmount-vsock clean
|
||||||
|
$(MAKE) -C iptables clean
|
||||||
|
@ -60,6 +60,9 @@ start()
|
|||||||
|
|
||||||
DOCKER_LOGFILE="/var/log/docker.log"
|
DOCKER_LOGFILE="/var/log/docker.log"
|
||||||
|
|
||||||
|
# Allow iptables to be overriden
|
||||||
|
export PATH=/usr/local/sbin:$PATH
|
||||||
|
|
||||||
start-stop-daemon --start --quiet \
|
start-stop-daemon --start --quiet \
|
||||||
--background \
|
--background \
|
||||||
--exec ${command} \
|
--exec ${command} \
|
||||||
|
1
alpine/packages/iptables/.gitignore
vendored
Normal file
1
alpine/packages/iptables/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
iptables
|
7
alpine/packages/iptables/Dockerfile
Normal file
7
alpine/packages/iptables/Dockerfile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
FROM ocaml/opam:alpine
|
||||||
|
RUN sudo apk add m4
|
||||||
|
RUN opam install ocamlfind astring -y
|
||||||
|
WORKDIR /app
|
||||||
|
ADD . /app
|
||||||
|
RUN sudo chown -R opam /app
|
||||||
|
RUN opam config exec -- ocamlfind ocamlopt -package unix,astring -linkpkg -o iptables main.ml
|
9
alpine/packages/iptables/Makefile
Normal file
9
alpine/packages/iptables/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
all: iptables
|
||||||
|
|
||||||
|
iptables: Dockerfile main.ml
|
||||||
|
docker build -t iptables:build .
|
||||||
|
docker run --rm iptables:build cat /app/iptables > iptables
|
||||||
|
chmod 755 iptables
|
||||||
|
|
||||||
|
clean:
|
||||||
|
docker images -q iptables:build | xargs docker rmi -f || true
|
100
alpine/packages/iptables/main.ml
Normal file
100
alpine/packages/iptables/main.ml
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
(* ocamlfind ocamlopt -package unix,astring -linkpkg -o iptables iptables.ml *)
|
||||||
|
|
||||||
|
(*
|
||||||
|
--wait -t nat -I DOCKER-INGRESS -p tcp --dport 80 -j DNAT --to-destination 172.18.0.2:80
|
||||||
|
--wait -t nat -D DOCKER-INGRESS -p tcp --dport 80 -j DNAT --to-destination 172.18.0.2:80
|
||||||
|
*)
|
||||||
|
|
||||||
|
let _iptables = "/sbin/iptables"
|
||||||
|
let _proxy = "/usr/bin/docker-proxy"
|
||||||
|
let _pid_dir = "/var/run/service-port-opener"
|
||||||
|
|
||||||
|
type port = {
|
||||||
|
proto: string;
|
||||||
|
dport: string; (* host port *)
|
||||||
|
ip: string; (* container ip *)
|
||||||
|
port: string; (* container port *)
|
||||||
|
}
|
||||||
|
|
||||||
|
let log_fd = Unix.openfile "/var/log/service-port-opener.log" [ Unix.O_WRONLY; Unix.O_APPEND; Unix.O_CREAT ] 0o0644
|
||||||
|
|
||||||
|
let logf fmt =
|
||||||
|
Printf.ksprintf (fun s ->
|
||||||
|
let s = s ^ "\n" in
|
||||||
|
let rec loop ofs remaining =
|
||||||
|
if remaining > 0 then begin
|
||||||
|
let n = Unix.write log_fd s ofs remaining in
|
||||||
|
loop (ofs + n) (remaining - n)
|
||||||
|
end in
|
||||||
|
loop 0 (String.length s)
|
||||||
|
) fmt
|
||||||
|
|
||||||
|
let pid_filename { proto; dport; ip; port } =
|
||||||
|
Printf.sprintf "%s/%s.%s.%s.%s.pid" _pid_dir proto dport ip port
|
||||||
|
|
||||||
|
let insert ({ proto; dport; ip; port } as p) =
|
||||||
|
let filename = pid_filename p in
|
||||||
|
logf "insert: creating a proxy for %s" filename;
|
||||||
|
let args = [ _proxy; "-proto"; proto; "-container-ip"; ip; "-container-port"; port; "-host-ip"; "0.0.0.0"; "-host-port"; dport; "-i"; "-no-local-ip" ] in
|
||||||
|
let pid = Unix.fork () in
|
||||||
|
if pid == 0 then begin
|
||||||
|
logf "binary = %s args = %s" _proxy (String.concat "; " args);
|
||||||
|
(* Close the vast number of fds I've inherited from docker *)
|
||||||
|
(* TODO(djs55): revisit, possibly by filing a docker/docker issue *)
|
||||||
|
for i = 0 to 1023 do
|
||||||
|
let fd : Unix.file_descr = Obj.magic i in
|
||||||
|
try Unix.close fd with Unix.Unix_error(Unix.EBADF, _, _) -> ()
|
||||||
|
done;
|
||||||
|
let null = Unix.openfile "/dev/null" [ Unix.O_RDWR ] 0 in
|
||||||
|
Unix.dup2 null Unix.stdin;
|
||||||
|
Unix.dup2 null Unix.stdout;
|
||||||
|
Unix.dup2 null Unix.stderr;
|
||||||
|
(try Unix.execv _proxy (Array.of_list args) with e -> logf "Failed with %s" (Printexc.to_string e));
|
||||||
|
exit 1
|
||||||
|
end else begin
|
||||||
|
(* write pid to a file (not atomically) *)
|
||||||
|
let oc = open_out filename in
|
||||||
|
output_string oc (string_of_int pid);
|
||||||
|
close_out oc
|
||||||
|
end
|
||||||
|
|
||||||
|
let delete ({ proto; dport; ip; port } as p) =
|
||||||
|
let filename = pid_filename p in
|
||||||
|
logf "delete: removing a proxy for %s" filename;
|
||||||
|
(* read the pid from a file *)
|
||||||
|
try
|
||||||
|
let ic = open_in filename in
|
||||||
|
let pid = int_of_string (input_line ic) in
|
||||||
|
logf "Sending SIGTERM to %d" pid;
|
||||||
|
Unix.kill pid Sys.sigterm;
|
||||||
|
Unix.unlink filename
|
||||||
|
with e ->
|
||||||
|
logf "delete: failed to remove proxy for %s: %s" filename (Printexc.to_string e);
|
||||||
|
()
|
||||||
|
|
||||||
|
let parse_ip_port ip_port = match Astring.String.cut ~sep:":" ip_port with
|
||||||
|
| None ->
|
||||||
|
failwith ("Failed to parse <ip:port>:" ^ ip_port)
|
||||||
|
| Some (ip, port) ->
|
||||||
|
ip, port
|
||||||
|
|
||||||
|
let _ =
|
||||||
|
( try Unix.mkdir _pid_dir 0o0755 with Unix.Unix_error(Unix.EEXIST, _, _) -> () );
|
||||||
|
let port_forwarding =
|
||||||
|
try
|
||||||
|
let ic = open_in "/Database/branch/master/ro/com.docker.driver.amd64-linux/native/port-forwarding" in
|
||||||
|
bool_of_string (String.trim (input_line ic))
|
||||||
|
with _ -> false in
|
||||||
|
logf "port_forwarding=%b intercepted arguments [%s]" port_forwarding (String.concat "; " (Array.to_list Sys.argv));
|
||||||
|
if port_forwarding then begin
|
||||||
|
match Array.to_list Sys.argv with
|
||||||
|
| [ _; "--wait"; "-t"; "nat"; "-I"; "DOCKER-INGRESS"; "-p"; proto; "--dport"; dport; "-j"; "DNAT"; "--to-destination"; ip_port ] ->
|
||||||
|
let ip, port = parse_ip_port ip_port in
|
||||||
|
insert { proto; dport; ip; port }
|
||||||
|
| [ _; "--wait"; "-t"; "nat"; "-D"; "DOCKER-INGRESS"; "-p"; proto; "--dport"; dport; "-j"; "DNAT"; "--to-destination"; ip_port ] ->
|
||||||
|
let ip, port = parse_ip_port ip_port in
|
||||||
|
delete { proto; dport; ip; port }
|
||||||
|
| _ ->
|
||||||
|
()
|
||||||
|
end;
|
||||||
|
Unix.execv _iptables Sys.argv
|
@ -11,22 +11,31 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func onePort() {
|
func onePort() {
|
||||||
host, _, container := parseHostContainerAddrs()
|
host, _, container, localIP := parseHostContainerAddrs()
|
||||||
|
|
||||||
ipP, err := libproxy.NewIPProxy(host, container)
|
var ipP libproxy.Proxy
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if localIP {
|
||||||
|
ipP, err = libproxy.NewIPProxy(host, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sendError(err)
|
sendError(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctl, err := exposePort(host, container)
|
ctl, err := exposePort(host, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sendError(err)
|
sendError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go handleStopSignals(ipP)
|
go handleStopSignals()
|
||||||
// TODO: avoid this line if we are running in a TTY
|
// TODO: avoid this line if we are running in a TTY
|
||||||
sendOK()
|
sendOK()
|
||||||
|
if ipP != nil {
|
||||||
ipP.Run()
|
ipP.Run()
|
||||||
|
} else {
|
||||||
|
select{} // sleep forever
|
||||||
|
}
|
||||||
ctl.Close() // ensure ctl remains alive and un-GCed until here
|
ctl.Close() // ensure ctl remains alive and un-GCed until here
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"proxy/libproxy"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var interactiveMode bool
|
var interactiveMode bool
|
||||||
@ -48,7 +46,7 @@ var vSockUDPPortOffset = 0x20000
|
|||||||
|
|
||||||
// parseHostContainerAddrs parses the flags passed on reexec to create the TCP or UDP
|
// parseHostContainerAddrs parses the flags passed on reexec to create the TCP or UDP
|
||||||
// net.Addrs to map the host and container ports
|
// net.Addrs to map the host and container ports
|
||||||
func parseHostContainerAddrs() (host net.Addr, port int, container net.Addr) {
|
func parseHostContainerAddrs() (host net.Addr, port int, container net.Addr, localIP bool) {
|
||||||
var (
|
var (
|
||||||
proto = flag.String("proto", "tcp", "proxy protocol")
|
proto = flag.String("proto", "tcp", "proxy protocol")
|
||||||
hostIP = flag.String("host-ip", "", "host ip")
|
hostIP = flag.String("host-ip", "", "host ip")
|
||||||
@ -56,6 +54,7 @@ func parseHostContainerAddrs() (host net.Addr, port int, container net.Addr) {
|
|||||||
containerIP = flag.String("container-ip", "", "container ip")
|
containerIP = flag.String("container-ip", "", "container ip")
|
||||||
containerPort = flag.Int("container-port", -1, "container port")
|
containerPort = flag.Int("container-port", -1, "container port")
|
||||||
interactive = flag.Bool("i", false, "print success/failure to stdout/stderr")
|
interactive = flag.Bool("i", false, "print success/failure to stdout/stderr")
|
||||||
|
noLocalIP = flag.Bool("no-local-ip", false, "bind only on the Host, not in the VM")
|
||||||
)
|
)
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -73,17 +72,15 @@ func parseHostContainerAddrs() (host net.Addr, port int, container net.Addr) {
|
|||||||
default:
|
default:
|
||||||
log.Fatalf("unsupported protocol %s", *proto)
|
log.Fatalf("unsupported protocol %s", *proto)
|
||||||
}
|
}
|
||||||
|
localIP = ! *noLocalIP
|
||||||
return host, port, container
|
return host, port, container, localIP
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleStopSignals(p libproxy.Proxy) {
|
func handleStopSignals() {
|
||||||
s := make(chan os.Signal, 10)
|
s := make(chan os.Signal, 10)
|
||||||
signal.Notify(s, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP)
|
signal.Notify(s, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP)
|
||||||
|
|
||||||
for range s {
|
for range s {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
// The vsock proxy cannot be shutdown the same way as the TCP one:
|
|
||||||
//p.Close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user