Files
linuxkit/alpine/packages/iptables/main.ml
Justin Cormack 545b12ee7d Explicitly use slirp-proxy in iptables
So as to allow a read only root filesystem, we use the proxy
path config option to override the Docker proxy for 1.13.

This means that the iptables override needs to call this binary
not the original docker-proxy binary to allow port forwarding.

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
2016-11-23 13:48:27 +00:00

95 lines
3.5 KiB
OCaml

(* 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/slirp-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 syslog = Syslog.openlog ~facility:`LOG_SECURITY "iptables-wrapper"
let logf fmt =
Printf.ksprintf (fun s ->
Syslog.syslog syslog `LOG_INFO 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