Hi, folks, I recently became interested in the jail code and have been very impressed with what I have seen so far. The one thing I found a bit surprising was the lack of support for multiple IP addresses in jail environments. I did some research into the issue, and I found the various posts discussing why this decision was made.
While a ``true'' multiple IP address implementation (INADDR_ANY, loopback, etc.) may be rather involved, getting more than one IP address into the jailed environment might be much simpler. Here is my proposal: Rather than specifying a single IP address when constructing the jail, supply an IP address and netmask. The kernel can then use the IP address in conjunction with the netmask to determine what range of addresses are allowed in the jail without having to run through an actual list of addresses. This approach is similar to how ISPs assign CIDR blocks to their customers. It has various advantages and disadvantages over the method of providing a list of allowed addresses. I consider its primary advantage to be that it is extremely simple to implement (as can be seen by the attached diff) and does not affect jail's runtime performance. Granted, this method does not solve the INADDR_ANY and localhost issues, but any solution to that side of the jail puzzle is sure to be an invasive one. The attached diff is based on 4.6-RELEASE. To use it, build and install the jail binary and a new kernel. By default, this diff results in a jail binary that acts the same as before. Adding a ``/ne.tm.as.k'' to the jail call will allow the jail to allocate any of the IP addresses in the netmask. For example.. jail /home/jail myhost 10.20.30.8/255.255.255.248 /bin/sh ..would allow the jail to use all of the following addresses.. 10.20.30.8 10.20.30.9 10.20.30.10 10.20.30.11 10.20.30.12 10.20.30.13 10.20.30.14 10.20.30.15 INADDR_ANY and 127.0.0.1 still use the first address. I changed jail's version number (from 0 to 1) as this affects the syscall. I look forward to your comments, suggestions, criticisms, etc. Thank you for your time! Michael Alyn Miller ------------------------------- The best kept secret in e-mail. http://eioMAIL.com/
*** sys/kern/kern_jail.c.orig Thu Aug 16 18:00:26 2001 --- sys/kern/kern_jail.c Tue Jun 18 13:52:27 2002 *************** *** 62,68 **** error = copyin(uap->jail, &j, sizeof j); if (error) return (error); ! if (j.version != 0) return (EINVAL); MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK); bzero((caddr_t)pr, sizeof *pr); --- 62,68 ---- error = copyin(uap->jail, &j, sizeof j); if (error) return (error); ! if (j.version != 1) return (EINVAL); MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK); bzero((caddr_t)pr, sizeof *pr); *************** *** 70,75 **** --- 70,76 ---- if (error) goto bail; pr->pr_ip = j.ip_number; + pr->pr_mask = j.ip_mask; ca.path = j.path; error = chroot(p, &ca); *************** *** 111,117 **** *ip = htonl(p->p_prison->pr_ip); return (0); } ! if (p->p_prison->pr_ip != tmp) return (1); return (0); } --- 112,119 ---- *ip = htonl(p->p_prison->pr_ip); return (0); } ! if ((p->p_prison->pr_mask & p->p_prison->pr_ip) ! != (p->p_prison->pr_mask & tmp)) return (1); return (0); } *** sys/netinet/in_pcb.c.orig Wed May 1 19:36:50 2002 --- sys/netinet/in_pcb.c Tue Jun 18 13:52:15 2002 *************** *** 1028,1034 **** { if (!p->p_prison) return (0); ! if (ntohl(inp->inp_laddr.s_addr) == p->p_prison->pr_ip) return (0); return (1); } --- 1028,1035 ---- { if (!p->p_prison) return (0); ! if ((p->p_prison->pr_mask & ntohl(inp->inp_laddr.s_addr)) ! == (p->p_prison->pr_mask & p->p_prison->pr_ip)) return (0); return (1); } *** sys/sys/jail.h.orig Wed Nov 1 09:58:06 2000 --- sys/sys/jail.h Tue Jun 18 13:33:28 2002 *************** *** 18,23 **** --- 18,24 ---- char *path; char *hostname; u_int32_t ip_number; + u_int32_t ip_mask; }; #ifndef _KERNEL *************** *** 40,45 **** --- 41,47 ---- int pr_ref; char pr_host[MAXHOSTNAMELEN]; u_int32_t pr_ip; + u_int32_t pr_mask; void *pr_linux; }; *** usr.sbin/jail/jail.c.orig Mon Jul 30 03:19:54 2001 --- usr.sbin/jail/jail.c Tue Jun 18 14:28:36 2002 *************** *** 24,40 **** struct jail j; int i; struct in_addr in; if (argc < 5) ! errx(1, "Usage: %s path hostname ip-number command ...\n", argv[0]); i = chdir(argv[1]); if (i) err(1, "chdir %s", argv[1]); memset(&j, 0, sizeof(j)); ! j.version = 0; j.path = argv[1]; j.hostname = argv[2]; i = inet_aton(argv[3], &in); if (!i) errx(1, "Couldn't make sense of ip-number\n"); --- 24,51 ---- struct jail j; int i; struct in_addr in; + char *p; if (argc < 5) ! errx(1, "Usage: %s path hostname ip-number[/ip-mask] command ...\n", argv[0]); i = chdir(argv[1]); if (i) err(1, "chdir %s", argv[1]); memset(&j, 0, sizeof(j)); ! j.version = 1; j.path = argv[1]; j.hostname = argv[2]; + p = strchr(argv[3], '/'); + if (p != NULL) { + i = inet_aton(p + 1, &in); + if (!i) + errx(1, "Couldn't make sense of ip-mask\n"); + j.ip_mask = ntohl(in.s_addr); + *p = '\0'; + } else { + j.ip_mask = 0xffffffff; + } i = inet_aton(argv[3], &in); if (!i) errx(1, "Couldn't make sense of ip-number\n");