RFC: ip_nat|conntrack_h323.c on 2.6, first preview
cover RFC: ip_nat|conntrack_h323.c on 2.6, first preview
Hi,
I have worked a bit on porting the H.323 conntrack module to Linux 2.6. Here is my first preview. Both connection tracking and NAT work well in my home network (gnomemeeting and ohphone, tunneling disabled).
It's still the old brute force method, no real protocol evaluation is performed. I will implement that the "right" way after the port to the Linux 2.6 API is finished and tested. The current algorithm is not recommended for production environments, because it is insecure, sometimes buggy and horribly inefficient.
The patches apply to patch-o-matic-ng from svn. Due to recent API changes, you need kernel 2.6.10-mm2 or later. I am currently using 2.6.11-rc1.
Using the module is easy: patch your kernel as usual with patch-o-matic-ng, enable H.323 connection tracking and NAT in the kernel configuration, boot the new kernel. Now the module should see all incoming, outgoing and forwarded TCP connections on port 1720, and lets the state module know about them.
I would appreciate comments and discussion about my patches and the H.323 module.
Max
PATCH 1/5 update kernel requires
this patch sets the kernel requirements to 2.6.10-mm2 or later
Wed Jan 19 01:31:26 CET 2005 [email protected]
* updated kernel requires
h323-conntrack-nat/info +1 -1
@@ -1,4 +1,4 @@ Author: Jozsef Kadlecsik <[email protected]> Status: Alpha Repository: extra -Requires: linux < 2.6.0 +Requires: linux >= 2.6.10-mm2
PATCH 2/5 author update
In reply to Max Kellermannadd myself as module author
Re: [PATCH pom-ng 2/5] author update
Quoted 1 line · Max Kellermann
add myself as module author
oh no, the patchfile was missing.
Wed Jan 19 01:32:02 CET 2005 [email protected]
* added new author
h323-conntrack-nat/info +1 -1
@@ -1,4 +1,4 @@ -Author: Jozsef Kadlecsik <[email protected]> +Author: Jozsef Kadlecsik <[email protected]>, Max Kellermann <[email protected]> Status: Alpha Repository: extra Requires: linux >= 2.6.10-mm2
h323-conntrack-nat/linux/net/ipv4/netfilter/ip_conntrack_h323.c +1 -0
@@ -1,6 +1,7 @@/* * H.323 'brute force' extension for H.323 connection tracking. * Jozsef Kadlecsik <[email protected]> +* (c) 2005 Max Kellermann <[email protected]> * * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project. * (http://www.coritel.it/projects/sofia/nat/)
h323-conntrack-nat/linux/net/ipv4/netfilter/ip_nat_h323.c +1 -0
@@ -1,6 +1,7 @@/* * H.323 'brute force' extension for NAT alteration. * Jozsef Kadlecsik <[email protected]> +* (c) 2005 Max Kellermann <[email protected]> * * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project. * (http://www.coritel.it/projects/sofia/nat.html)
PATCH 3/5 whitespace and indentation
In reply to Max Kellermannfix indentation.
Wed Jan 19 01:33:59 CET 2005 [email protected]
* whitespace fixes
h323-conntrack-nat/linux/net/ipv4/netfilter/ip_conntrack_h323.c +13 -13
@@ -1,5 +1,5 @@ -/* -* H.323 'brute force' extension for H.323 connection tracking. +/* +* H.323 'brute force' extension for H.323 connection tracking. * Jozsef Kadlecsik <[email protected]> * (c) 2005 Max Kellermann <[email protected]> *
@@ -61,7 +61,7 @@/* Can't track connections formed before we registered */ if (!info)return NF_ACCEPT ; - +/* Until there's been traffic both ways, don't look in packets. */ if (ctinfo !=IP_CT_ESTABLISHED && ctinfo !=IP_CT_ESTABLISHED +IP_CT_IS_REPLY ) {
@@ -104,7 +104,7 @@ exp_info->offset = i; exp->seq =ntohl (tcph->seq) + i; - + exp->tuple = ((struct ip_conntrack_tuple) { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
@@ -114,9 +114,9 @@ exp->mask = ((struct ip_conntrack_tuple ) { {0xFFFFFFFF , {0 } }, {0xFFFFFFFF , { .tcp = {0xFFFF } },0xFFFF }}); - + exp->expectfn =NULL ; - +/* Ignore failure; should only happen with NAT */ ip_conntrack_expect_related (ct, exp);
@@ -149,7 +149,7 @@ ct->helper = &h245;DEBUGP ("h225_expect: helper for %p added\n" , ct);WRITE_UNLOCK (&ip_conntrack_lock); - +return NF_ACCEPT ;/* unused */ }
@@ -170,7 +170,7 @@u_int16_t data_port;u_int32_t data_ip;unsigned int i; - +DEBUGP ("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n" ,NIPQUAD (iph->saddr),ntohs (tcph->source),NIPQUAD (iph->daddr),ntohs (tcph->dest));
@@ -201,7 +201,7 @@ NIPQUAD(iph->daddr));return NF_ACCEPT ; } - + data_limit = (unsigned char *) data + datalen;/* bytes: 0123 45 ipadrr port */
@@ -243,9 +243,9 @@ exp->mask = ((struct ip_conntrack_tuple ) { {0xFFFFFFFF , {0 } }, {0xFFFFFFFF , { .tcp = {0xFFFF } },0xFFFF }}); - + exp->expectfn = h225_expect; - +/* Ignore failure */ ip_conntrack_expect_related (ct, exp);
@@ -254,7 +254,7 @@ NIPQUAD(iph->saddr), ntohs(data_port));UNLOCK_BH (&ip_h323_lock); - } + } #ifdef CONFIG_IP_NF_NAT_NEEDED }else if (data_ip == iph->daddr) { data_port = *((u_int16_t *)(data +4 ));
@@ -299,7 +299,7 @@ static void __exit fini(void) { -/* Unregister H.225 helper */ +/* Unregister H.225 helper */ ip_conntrack_helper_unregister (&h225); }
h323-conntrack-nat/linux/net/ipv4/netfilter/ip_nat_h323.c +38 -38
182 lines not on this page · raw message
PATCH 4/5 use c99 initializers
In reply to Max Kellermannuse c99 initializers
Wed Jan 19 01:34:09 CET 2005 [email protected]
* use c99 initializers
h323-conntrack-nat/linux/net/ipv4/netfilter/ip_conntrack_h323.c +22 -26
@@ -129,19 +129,16 @@ }/* H.245 helper is not registered! */ -static struct ip_conntrack_helper h245 = - { {NULL ,NULL }, -"H.245" ,/* name */ -IP_CT_HELPER_F_REUSE_EXPECT ,/* flags */ -NULL ,/* module */ -8 ,/* max_ expected */ -240 ,/* timeout */ - { {0 , {0 } },/* tuple */ - {0 , {0 },IPPROTO_TCP } }, - { {0 , {0xFFFF } },/* mask */ - {0 , {0 },0xFFFF } }, - h245_help/* helper */ - }; +static struct ip_conntrack_helper h245 = { + .name ="H.245" , + .flags =IP_CT_HELPER_F_REUSE_EXPECT , + .max_expected =8 , + .timeout =240 , + .tuple = { .dst = { .protonum =IPPROTO_TCP } }, + .mask = { .src = { .u = {0xFFFF } }, + .dst = { .protonum =0xFFFF } }, + .help = h245_help +};static int h225_expect (struct ip_conntrack *ct) {
@@ -278,19 +275,18 @@ } -static struct ip_conntrack_helper h225 = - { {NULL ,NULL }, -"H.225" ,/* name */ -IP_CT_HELPER_F_REUSE_EXPECT ,/* flags */ -THIS_MODULE ,/* module */ -2 ,/* max_expected */ -240 ,/* timeout */ - { {0 , {__constant_htons (H225_PORT ) } },/* tuple */ - {0 , {0 },IPPROTO_TCP } }, - { {0 , {0xFFFF } },/* mask */ - {0 , {0 },0xFFFF } }, - h225_help/* helper */ - }; +static struct ip_conntrack_helper h225 = { + .name ="H.225" , + .flags =IP_CT_HELPER_F_REUSE_EXPECT , + .me =THIS_MODULE , + .max_expected =2 , + .timeout =240 , + .tuple = { .src = { .u = {__constant_htons (H225_PORT ) } }, + .dst = { .protonum =IPPROTO_TCP } }, + .mask = { .src = { .u = {0xFFFF } }, + .dst = { .protonum =0xFFFF } }, + .help = h225_help +};static int __init init (void ) {
h323-conntrack-nat/linux/net/ipv4/netfilter/ip_nat_h323.c +24 -24
60 lines not on this page · raw message
PATCH 5/5 port the module to Linux 2.6
In reply to Max Kellermannnow this is the "real" patch which ports the module to the Linux 2.6 API.
Wed Jan 19 01:34:37 CET 2005 [email protected]
* ported to linux 2.6
h323-conntrack-nat/linux/net/ipv4/netfilter/ip_conntrack_h323.c +88 -65
@@ -27,6 +27,10 @@MODULE_DESCRIPTION ("H.323 'brute force' connection tracking module" );MODULE_LICENSE ("GPL" ); +/* This is slow, but it's simple. --RR */ +static char h323_buffer[65536 ]; +static DECLARE_LOCK (h323_buffer_lock); +DECLARE_LOCK (ip_h323_lock);struct module *ip_conntrack_h323 =THIS_MODULE ;
@@ -37,30 +41,23 @@#endif /* FIXME: This should be in userspace. Later. */ -static int h245_help (const struct iphdr *iph,size_t len, +static int h245_help (struct sk_buff *skb,struct ip_conntrack *ct,enum ip_conntrack_info ctinfo) { -struct tcphdr *tcph = (void *)iph + iph->ihl *4 ; -unsigned char *data = (unsigned char *) tcph + tcph->doff *4 ; +struct iphdr *iph = skb->nh.iph; +struct tcphdr _tcph, *tcph; +unsigned char *data;unsigned char *data_limit; -u_int32_t tcplen = len - iph->ihl *4 ; -u_int32_t datalen = tcplen - tcph->doff *4 ; +unsigned dataoff, datalen;int dir =CTINFO2DIR (ctinfo);struct ip_ct_h225_master *info = &ct->help.ct_h225_info; -struct ip_conntrack_expect expect, *exp = &expect; -struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info; +struct ip_conntrack_expect *exp; +struct ip_ct_h225_expect *exp_info;u_int16_t data_port;u_int32_t data_ip;unsigned int i; - -DEBUGP ("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n" , -NIPQUAD (iph->saddr),ntohs (tcph->source), -NIPQUAD (iph->daddr),ntohs (tcph->dest)); - -/* Can't track connections formed before we registered */ -if (!info) -return NF_ACCEPT ; +int ret;/* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED
@@ -69,34 +66,49 @@return NF_ACCEPT ; } -/* Not whole TCP header or too short packet? */ -if (tcplen <sizeof (struct tcphdr ) || tcplen < tcph->doff *4 +5 ) { -DEBUGP ("ct_h245_help: tcplen = %u\n" , (unsigned )tcplen); + tcph =skb_header_pointer (skb, skb->nh.iph->ihl*4 , +sizeof (_tcph), &_tcph); +if (tcph ==NULL )return NF_ACCEPT ; - } -/* Checksum invalid? Ignore. */ -/* FIXME: Source route IP option packets --RR */ -if (tcp_v4_check (tcph, tcplen, iph->saddr, iph->daddr, -csum_partial ((char *)tcph, tcplen,0 ))) { -DEBUGP ("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n" , - tcph, tcplen,NIPQUAD (iph->saddr), -NIPQUAD (iph->daddr)); +DEBUGP ("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n" , +NIPQUAD (iph->saddr),ntohs (tcph->source), +NIPQUAD (iph->daddr),ntohs (tcph->dest)); + + dataoff = skb->nh.iph->ihl*4 + tcph->doff*4 ; +/* No data? */ +if (dataoff >= skb->len) { +DEBUGP ("ct_h245_help: skblen = %u\n" , skb->len);return NF_ACCEPT ; } + datalen = skb->len - dataoff; - data_limit = (unsigned char *) data + datalen; +LOCK_BH (&h323_buffer_lock); + data =skb_header_pointer (skb, dataoff, + datalen, h323_buffer); +BUG_ON (data ==NULL ); + + data_limit = data + datalen -6 ;/* bytes: 0123 45 ipadrr port */ -for (i =0 ; data < (data_limit -5 ); data++, i++) { +for (i =0 ; data <= data_limit; data++, i++) { data_ip = *((u_int32_t *)data);if (data_ip == iph->saddr) { data_port = *((u_int16_t *)(data +4 )); -memset (&expect,0 ,sizeof (expect)); +/* update the H.225 info */ DEBUGP ("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n" ,NIPQUAD (ct->tuplehash[!dir].tuple.src.ip),NIPQUAD (iph->saddr),ntohs (data_port)); + + exp =ip_conntrack_expect_alloc (); +if (exp ==NULL ) { + ret =NF_ACCEPT ; + goto out; + } + + exp_info = &exp->help.exp_h225_info; +LOCK_BH (&ip_h323_lock); info->is_h225 =H225_PORT +1 ; exp_info->port = data_port;
@@ -118,14 +130,16 @@ exp->expectfn =NULL ;/* Ignore failure; should only happen with NAT */ -ip_conntrack_expect_related (ct, exp); +ip_conntrack_expect_related (exp, ct);UNLOCK_BH (&ip_h323_lock); } } -return NF_ACCEPT ; - + ret =NF_ACCEPT ; + out: +UNLOCK_BH (&h323_buffer_lock); +return ret; }/* H.245 helper is not registered! */
@@ -151,30 +165,23 @@ }/* FIXME: This should be in userspace. Later. */ -static int h225_help (const struct iphdr *iph,size_t len, +static int h225_help (struct sk_buff *skb,struct ip_conntrack *ct,enum ip_conntrack_info ctinfo) { -struct tcphdr *tcph = (void *)iph + iph->ihl *4 ; -unsigned char *data = (unsigned char *) tcph + tcph->doff *4 ; +struct iphdr *iph = skb->nh.iph; +struct tcphdr _tcph, *tcph; +unsigned char *data;unsigned char *data_limit; -u_int32_t tcplen = len - iph->ihl *4 ; -u_int32_t datalen = tcplen - tcph->doff *4 ; +unsigned dataoff, datalen;int dir =CTINFO2DIR (ctinfo);struct ip_ct_h225_master *info = &ct->help.ct_h225_info; -struct ip_conntrack_expect expect, *exp = &expect; -struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info; +struct ip_conntrack_expect *exp; +struct ip_ct_h225_expect *exp_info;u_int16_t data_port;u_int32_t data_ip;unsigned int i; - -DEBUGP ("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n" , -NIPQUAD (iph->saddr),ntohs (tcph->source), -NIPQUAD (iph->daddr),ntohs (tcph->dest)); - -/* Can't track connections formed before we registered */ -if (!info) -return NF_ACCEPT ; +int ret;/* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED
@@ -183,26 +190,32 @@return NF_ACCEPT ; } -/* Not whole TCP header or too short packet? */ -if (tcplen <sizeof (struct tcphdr ) || tcplen < tcph->doff *4 +5 ) { -DEBUGP ("ct_h225_help: tcplen = %u\n" , (unsigned )tcplen); + tcph =skb_header_pointer (skb, skb->nh.iph->ihl*4 , +sizeof (_tcph), &_tcph); +if (tcph ==NULL )return NF_ACCEPT ; - } -/* Checksum invalid? Ignore. */ -/* FIXME: Source route IP option packets --RR */ -if (tcp_v4_check (tcph, tcplen, iph->saddr, iph->daddr, -csum_partial ((char *)tcph, tcplen,0 ))) { -DEBUGP ("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n" , - tcph, tcplen,NIPQUAD (iph->saddr), -NIPQUAD (iph->daddr)); +DEBUGP ("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n" , +NIPQUAD (iph->saddr),ntohs (tcph->source), +NIPQUAD (iph->daddr),ntohs (tcph->dest)); + + dataoff = skb->nh.iph->ihl*4 + tcph->doff*4 ; +/* No data? */ +if (dataoff >= skb->len) { +DEBUGP ("ct_h225_help: skblen = %u\n" , skb->len);return NF_ACCEPT ; } + datalen = skb->len - dataoff; + +LOCK_BH (&h323_buffer_lock); + data =skb_header_pointer (skb, dataoff, + datalen, h323_buffer); +BUG_ON (data ==NULL ); - data_limit = (unsigned char *) data + datalen; + data_limit = data + datalen -6 ;/* bytes: 0123 45 ipadrr port */ -for (i =0 ; data < (data_limit -5 ); data++, i++) { +for (i =0 ; data <= data_limit; data++, i++) { data_ip = *((u_int32_t *)data);if (data_ip == iph->saddr) { data_port = *((u_int16_t *)(data +4 ));
@@ -220,9 +233,15 @@UNLOCK_BH (&ip_h323_lock);#endif }else { -memset (&expect,0 ,sizeof (expect)); -/* update the H.225 info */ + exp =ip_conntrack_expect_alloc (); +if (exp ==NULL ) { + ret =NF_ACCEPT ; + goto out; + } + + exp_info = &exp->help.exp_h225_info; +LOCK_BH (&ip_h323_lock); info->is_h225 =H225_PORT ; exp_info->port = data_port;
@@ -244,7 +263,7 @@ exp->expectfn = h225_expect;/* Ignore failure */ -ip_conntrack_expect_related (ct, exp); +ip_conntrack_expect_related (exp, ct); DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n", NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
@@ -271,8 +290,10 @@ } } -return NF_ACCEPT ; - + ret =NF_ACCEPT ; + out: +UNLOCK_BH (&h323_buffer_lock); +return ret; }static struct ip_conntrack_helper h225 = {
@@ -301,5 +322,7 @@EXPORT_SYMBOL (ip_h323_lock); +PROVIDES_CONNTRACK (h225); +PROVIDES_CONNTRACK (h245);module_init (init);module_exit (fini);
h323-conntrack-nat/linux/net/ipv4/netfilter/ip_nat_h323.c +58 -74
217 lines not on this page · raw message
h323-conntrack-nat/linux/net/ipv4/netfilter/Makefile.ladd +0 -3
@@ -2,8 +2,5 @@ # H.323 support obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o -ifdef CONFIG_IP_NF_H323 - export-objs += ip_conntrack_h323.o -endif obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
Hi,
Quoted 10 lines · Max Kellermann
I have worked a bit on porting the H.323 conntrack module to Linux 2.6. Here is my first preview. Both connection tracking and NAT work well in my home network (gnomemeeting and ohphone, tunneling disabled).
It's still the old brute force method, no real protocol evaluation is performed. I will implement that the "right" way after the port to the Linux 2.6 API is finished and tested. The current algorithm is not recommended for production environments, because it is insecure, sometimes buggy and horribly inefficient.
Yes, exactly. That was why I refrained from porting it to 2.6...
If you want to write a decent helper, then ethereal has got a H.323 (ASN) decoder written in C, which could probably be re-used. :-)
Quoted 3 lines
The patches apply to patch-o-matic-ng from svn. Due to recent API changes, you need kernel 2.6.10-mm2 or later. I am currently using 2.6.11-rc1.
As for the patch, thus we would overwrite the 2.4 version in pom-ng. Please put all the files into a h323-conntrack-nat/linux-2.6 subdirectory so that the support for 2.4 can be kept. (The README.newpatches file in pom-ng describes in detail how to create a new patch.)
Please note, pom-ng is unable to take into account the extra version. As requirements you should speficy something like
Requires: linux-2.6 >= 2.6.11
Best regards,
Jozsef
-
E-mail : [email protected], [email protected] PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
H-1525 Budapest 114, POB. 49, Hungary
Quoted 2 lines · Jozsef Kadlecsik
If you want to write a decent helper, then ethereal has got a H.323 (ASN) decoder written in C, which could probably be re-used. :-)
Good idea. This parser already helped me during development.
Quoted 5 lines
As for the patch, thus we would overwrite the 2.4 version in pom-ng. Please put all the files into a h323-conntrack-nat/linux-2.6 subdirectory so that the support for 2.4 can be kept. (The README.newpatches file in pom-ng describes in detail how to create a new patch.)
Ok.
Someone with svn access should copy the directory h323-conntrack-nat/linux to h323-conntrack-nat/linux-2.6. After that, I can send patches which modify these copies.
Quoted 5 lines
Please note, pom-ng is unable to take into account the extra version. As requirements you should speficy something like
Requires: linux-2.6 >= 2.6.11
Will this still work with the old 2.4 version then? Is this dependency ignored when the user wants the old version (and thus only has kernel 2.4)?
Max
Quoted 13 lines · Jozsef Kadlecsik
Quoted 10 lines · Max Kellermann
I have worked a bit on porting the H.323 conntrack module to Linux 2.6. Here is my first preview. Both connection tracking and NAT work well in my home network (gnomemeeting and ohphone, tunneling disabled).
It's still the old brute force method, no real protocol evaluation is performed. I will implement that the "right" way after the port to the Linux 2.6 API is finished and tested. The current algorithm is not recommended for production environments, because it is insecure, sometimes buggy and horribly inefficient.
Quoted 4 lines
Yes, exactly. That was why I refrained from porting it to 2.6...
If you want to write a decent helper, then ethereal has got a H.323 (ASN) decoder written in C, which could probably be re-used. :-)
Yes... but do we really want a big ASN-1 parser in the kernel? Is there a nice way to have it rely on kernel facilities, while staying in userspace though?
Herve
Signature · 4 lines
_ (°= Hervé Eychenne //) v_/_ WallFire project: http://www.wallfire.org/
Quoted 3 lines · Herve Eychenne
Yes... but do we really want a big ASN-1 parser in the kernel? Is there a nice way to have it rely on kernel facilities, while staying in userspace though?
The module needs to know one thing: the location of the sender's IP and port within the data portion of the packet. It currently does that by looking for the raw IP, and using whatever follows as the port number.
I believe it's possible to implement a tiny parser without all the features we don't need. Though I havn't looked at the protocol in-depth yet.
Max
Quoted 6 lines · Herve Eychenne
Quoted 2 lines
If you want to write a decent helper, then ethereal has got a H.323 (ASN) decoder written in C, which could probably be re-used. :-)
Yes... but do we really want a big ASN-1 parser in the kernel? Is there a nice way to have it rely on kernel facilities, while staying in userspace though?
We don't really need the complete parsing of H.225/H.245 and that'd make the code a little bit simpler.
If ctnetlink would be in the vanilla kernel, we could rely on it as well:
the H.323 "helper" could just pass the packets to userspace for inspection and the expectations would then set up from there.
Best regards,
Jozsef
-
E-mail : [email protected], [email protected] PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
H-1525 Budapest 114, POB. 49, Hungary