免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6706 | 回复: 8
打印 上一主题 下一主题

[网络管理] platinum进来讨论一下(iptables nat方式) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-09-18 14:51 |显示全部楼层 |倒序浏览
你有没有研究一下iptables nat的方式?iptables 属于Symmetric NAT,不适合VOIP语音对话.你知道linux 如何实现Full Cone NAT ?

论坛徽章:
0
2 [报告]
发表于 2006-09-18 14:51 |显示全部楼层
谢谢!

论坛徽章:
0
3 [报告]
发表于 2006-09-19 08:02 |显示全部楼层
晕倒,呵呵.

论坛徽章:
0
4 [报告]
发表于 2006-09-19 14:05 |显示全部楼层
经过分析和实际测试发现,iptalbes 是对程性NAT.在经过NAT转换后的端口必须一一对应.更麻烦的是它有一个连接跟踪功能,能记录是否有相同的端口,如果有,自动把它端口修改.这样语音包就不能收到.
我看看是否iptables有相关补丁?应该没有,打算修改它源码.可参考资料..

论坛徽章:
0
5 [报告]
发表于 2006-09-19 14:06 |显示全部楼层

论坛徽章:
0
6 [报告]
发表于 2006-09-22 14:10 |显示全部楼层
那你说的意思就是做应用层网关了?
昨天我把一个支持SIP的patch移植进2.4.25内核.做了两个NAT 路由器.分别接在网络里.两个路由器下分别有一个PC1,PC2.发现PC1与PC2呼叫能建立会话,但语音包还是不能通.昏迷中.......

论坛徽章:
0
7 [报告]
发表于 2006-09-25 10:43 |显示全部楼层

  1. diff -urN linux2425_jffs2/include/linux/netfilter_ipv4/ip_conntrack_sip.h linux2425_jffs2/include/linux/netfilter_ipv4/ip_conntrack_sip.h
  2. --- linux2425_jffs2/include/linux/netfilter_ipv4/ip_conntrack_sip.h (revision 0)
  3. +++ linux2425_jffs2/include/linux/netfilter_ipv4/ip_conntrack_sip.h (revision 0)
  4. @@ -0,0 +1,75 @@
  5. +#ifndef __IP_CONNTRACK_SIP_H__
  6. +#define __IP_CONNTRACK_SIP_H__
  7. +/* SIP tracking. */
  8. +
  9. +#ifdef __KERNEL__
  10. +
  11. +#define SIP_PORT 5060
  12. +#define SIP_TIMEOUT 3600
  13. +
  14. +#define POS_VIA 0
  15. +#define POS_CONTACT 1
  16. +#define POS_CONTENT 2
  17. +#define POS_MEDIA 3
  18. +#define POS_OWNER 4
  19. +#define POS_CONECTION 5
  20. +#define POS_REQ_HEADER 6
  21. +#define POS_SDP_HEADER 7
  22. +
  23. +struct sip_header_nfo {
  24. + const char *lname;
  25. + size_t lnlen;
  26. + const char *sname;
  27. + size_t snlen;
  28. + const char *ln_str;
  29. + size_t ln_strlen;
  30. + int (*match_len)(const char *, const char *, int *);
  31. +
  32. +};
  33. +
  34. +extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
  35. + enum ip_conntrack_info ctinfo,
  36. + struct ip_conntrack *ct,
  37. + char **dptr);
  38. +
  39. +/* For NAT to hook in when on expect. */
  40. +extern unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
  41. + enum ip_conntrack_info ctinfo,
  42. + struct ip_conntrack_expect *exp,
  43. + char *dptr);
  44. +
  45. +extern int ct_sip_get_info(char *dptr, int dlen, int *matchoff,
  46. + int *matchlen, struct sip_header_nfo *hnfo);
  47. +
  48. +/* get line lenght until first CR or LF seen. */
  49. +static __inline__ int ct_sip_lnlen(char *line, char *limit)
  50. +{
  51. + char *k = line;
  52. +
  53. + while ((line <= limit) && (*line == '\r' || *line == '\n'))
  54. + line++;
  55. +
  56. + while (line <= limit) {
  57. + if (*line == '\r' || *line == '\n')
  58. + break;
  59. + line++;
  60. + }
  61. + return line - k;
  62. +}
  63. +
  64. +/* Linear string search, case sensitive. */
  65. +static __inline__ char *ct_sip_search(const char *needle, char *haystack,
  66. + int needle_len, int haystack_len)
  67. +{
  68. + char *limit = haystack + (haystack_len - needle_len);
  69. +
  70. + while (haystack <= limit) {
  71. + if (memcmp(haystack, needle, needle_len) == 0)
  72. + return haystack;
  73. + haystack++;
  74. + }
  75. + return NULL;
  76. +}
  77. +#endif /* __KERNEL__ */
  78. +
  79. +#endif /* __IP_CONNTRACK_SIP_H__ */
  80. diff -urN linux2425_jffs2/net/ipv4/netfilter/ip_conntrack_sip.c linux2425_jffs2/net/ipv4/netfilter/ip_conntrack_sip.c
  81. --- linux2425_jffs2/net/ipv4/netfilter/ip_conntrack_sip.c (revision 0)
  82. +++ linux2425_jffs2/net/ipv4/netfilter/ip_conntrack_sip.c (revision 0)
  83. @@ -0,0 +1,405 @@
  84. +/* SIP extension for IP connection tracking.
  85. + *
  86. + * (C) 2005 by Christian Hentschel <[email]chentschel@arnet.com.ar[/email]>
  87. + * based on RR's ip_conntrack_ftp.c and other modules.
  88. + *
  89. + * This program is free software; you can redistribute it and/or modify
  90. + * it under the terms of the GNU General Public License version 2 as
  91. + * published by the Free Software Foundation.
  92. + */
  93. +
  94. +#include <linux/config.h>
  95. +#include <linux/module.h>
  96. +#include <linux/netfilter.h>
  97. +#include <linux/ip.h>
  98. +#include <linux/ctype.h>
  99. +#include <net/checksum.h>
  100. +#include <net/udp.h>
  101. +
  102. +#include <linux/netfilter_ipv4/lockhelp.h>
  103. +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
  104. +#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
  105. +
  106. +MODULE_LICENSE("GPL");
  107. +MODULE_AUTHOR("Christian Hentschel <[email]chentschel@arnet.com.ar[/email]>");
  108. +MODULE_DESCRIPTION("SIP connection tracking helper");
  109. +
  110. +static DECLARE_LOCK(sipbf_lock);
  111. +
  112. +#define MAX_PORTS 8
  113. +static int ports[MAX_PORTS];
  114. +static int ports_c;
  115. +module_param_array(ports, int, &ports_c, 0400);
  116. +MODULE_PARM_DESC(ports, " port numbers of sip servers");
  117. +
  118. +static unsigned int sip_timeout = SIP_TIMEOUT;
  119. +
  120. +module_param(sip_timeout, int, 0600);
  121. +MODULE_PARM_DESC(sip_timeout, "timeout for the master sip session");
  122. +
  123. +unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
  124. + enum ip_conntrack_info ctinfo,
  125. + struct ip_conntrack *ct,
  126. + char **dptr);
  127. +EXPORT_SYMBOL_GPL(ip_nat_sip_hook);
  128. +
  129. +unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
  130. + enum ip_conntrack_info ctinfo,
  131. + struct ip_conntrack_expect *exp,
  132. + char *dptr);
  133. +EXPORT_SYMBOL_GPL(ip_nat_sdp_hook);
  134. +
  135. +int ct_sip_get_info(char *dptr, int dlen, int *matchoff, int *matchlen,
  136. + struct sip_header_nfo *hnfo);
  137. +
  138. +EXPORT_SYMBOL(ct_sip_get_info);
  139. +
  140. +#if 0
  141. +#define DEBUGP printk
  142. +#else
  143. +#define DEBUGP(format, args...)
  144. +#endif
  145. +
  146. +static int digits_len(const char *dptr, const char *limit, int *shift);
  147. +static int epaddr_len(const char *dptr, const char *limit, int *shift);
  148. +static int skp_digits_len(const char *dptr, const char *limit, int *shift);
  149. +static int skp_epaddr_len(const char *dptr, const char *limit, int *shift);
  150. +
  151. +struct sip_header_nfo ct_sip_hdrs[] = {
  152. + { /* Via header */
  153. + "Via:", sizeof("Via:") - 1,
  154. + "\r\nv:", sizeof("\r\nv:") - 1, /* rfc3261 says "end in CRLF" */
  155. + "UDP ", sizeof("UDP ") - 1,
  156. + epaddr_len
  157. + },
  158. + { /* Contact header */
  159. + "Contact:", sizeof("Contact:") - 1,
  160. + "\r\nm:", sizeof("\r\nm:") - 1,
  161. + "sip:", sizeof("sip:") - 1,
  162. + skp_epaddr_len
  163. + },
  164. + { /* Content length header */
  165. + "Content-Length:", sizeof("Content-Length:") - 1,
  166. + "\r\nl:", sizeof("\r\nl:") - 1,
  167. + ":", sizeof(":") - 1,
  168. + skp_digits_len
  169. + },
  170. + { /* SDP media info */
  171. + "\nm=", sizeof("\nm=") - 1,
  172. + "\rm=", sizeof("\rm=") - 1,
  173. + "audio ", sizeof("audio ") - 1,
  174. + digits_len
  175. + },
  176. + { /* SDP owner address*/
  177. + "\no=", sizeof("\no=") - 1,
  178. + "\ro=", sizeof("\ro=") - 1,
  179. + "IN IP4 ", sizeof("IN IP4 ") - 1,
  180. + epaddr_len
  181. + },
  182. + { /* SDP connection info */
  183. + "\nc=", sizeof("\nc=") - 1,
  184. + "\rc=", sizeof("\rc=") - 1,
  185. + "IN IP4 ", sizeof("IN IP4 ") - 1,
  186. + epaddr_len
  187. + },
  188. + { /* Requests headers */
  189. + "sip:", sizeof("sip:") - 1,
  190. + "sip:", sizeof("sip:") - 1, /* yes, i know..*/
  191. + "@", sizeof("@") - 1,
  192. + epaddr_len
  193. + },
  194. + { /* SDP version header */
  195. + "\nv=", sizeof("\nv=") - 1,
  196. + "\rv=", sizeof("\rv=") - 1,
  197. + "=", sizeof("=") - 1,
  198. + digits_len
  199. + }
  200. +};
  201. +EXPORT_SYMBOL(ct_sip_hdrs);
  202. +
  203. +
  204. +static int digits_len(const char *dptr, const char *limit, int *shift)
  205. +{
  206. + int len = 0;
  207. + while (dptr <= limit && isdigit(*dptr)) {
  208. + dptr++;
  209. + len++;
  210. + }
  211. + return len;
  212. +}
  213. +
  214. +/* get digits lenght, skiping blank spaces. */
  215. +static int skp_digits_len(const char *dptr, const char *limit, int *shift)
  216. +{
  217. + for (; dptr <= limit && *dptr == ' '; dptr++)
  218. + (*shift)++;
  219. +
  220. + return digits_len(dptr, limit, shift);
  221. +}
  222. +
  223. +/* Simple ipaddr parser.. */
  224. +static int parse_ipaddr(const char *cp, char **endp,
  225. + uint32_t *ipaddr, const char *limit)
  226. +{
  227. + unsigned long int val;
  228. + int i, digit = 0;
  229. +
  230. + for (i = 0, *ipaddr = 0; cp <= limit && i < 4; i++) {
  231. + digit = 0;
  232. + if (!isdigit(*cp))
  233. + break;
  234. +
  235. + val = simple_strtoul(cp, (char **)&cp, 10);
  236. + if (val > 0xFF)
  237. + return -1;
  238. +
  239. + ((uint8_t *)ipaddr)[i] = val;
  240. + digit = 1;
  241. +
  242. + if (*cp != '.')
  243. + break;
  244. + cp++;
  245. + }
  246. + if (!digit)
  247. + return -1;
  248. +
  249. + if (endp)
  250. + *endp = (char *)cp;
  251. +
  252. + return 0;
  253. +}
  254. +
  255. +/* skip ip address. returns it lenght. */
  256. +static int epaddr_len(const char *dptr, const char *limit, int *shift)
  257. +{
  258. + const char *aux = dptr;
  259. + uint32_t ip;
  260. +
  261. + if (parse_ipaddr(dptr, (char **)&dptr, &ip, limit) < 0) {
  262. + DEBUGP("ip: %s parse failed.!\n", dptr);
  263. + return 0;
  264. + }
  265. +
  266. + /* Port number */
  267. + if (*dptr == ':') {
  268. + dptr++;
  269. + dptr += digits_len(dptr, limit, shift);
  270. + }
  271. + return dptr - aux;
  272. +}
  273. +
  274. +/* get address lenght, skiping user info. */
  275. +static int skp_epaddr_len(const char *dptr, const char *limit, int *shift)
  276. +{
  277. + for (; dptr <= limit && *dptr != '@'; dptr++)
  278. + (*shift)++;
  279. +
  280. + if (*dptr == '@') {
  281. + dptr++;
  282. + (*shift)++;
  283. + return epaddr_len(dptr, limit, shift);
  284. + }
  285. + return 0;
  286. +}
  287. +
  288. +/* Returns 0 if not found, -1 error parsing. */
  289. +int ct_sip_get_info(char *dptr, int dlen,
  290. + int *matchoff, int *matchlen,
  291. + struct sip_header_nfo *hnfo)
  292. +{
  293. + char *limit = dptr + (dlen - hnfo->lnlen);
  294. + char *aux, *k = dptr;
  295. + int shift = 0;
  296. +
  297. + while (dptr <= limit) {
  298. + if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
  299. + (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0))
  300. + {
  301. + dptr++;
  302. + continue;
  303. + }
  304. + aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
  305. + ct_sip_lnlen(dptr, limit));
  306. + if (!aux) {
  307. + DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str, hnfo->lname);
  308. + return -1;
  309. + }
  310. + aux += hnfo->ln_strlen;
  311. +
  312. + *matchlen = hnfo->match_len(aux, limit, &shift);
  313. + if (!*matchlen)
  314. + return -1;
  315. +
  316. + *matchoff = (aux - k) + shift;
  317. +
  318. + DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname, *matchlen);
  319. + return 1;
  320. + }
  321. + DEBUGP("%s header not found.\n", hnfo->lname);
  322. + return 0;
  323. +}
  324. +
  325. +static int set_expected_rtp(struct sk_buff **pskb,
  326. + struct ip_conntrack *ct,
  327. + enum ip_conntrack_info ctinfo,
  328. + uint32_t ipaddr, uint16_t port,
  329. + char *dptr)
  330. +{
  331. + struct ip_conntrack_expect *exp;
  332. +
  333. + exp = ip_conntrack_expect_alloc();
  334. + if (exp == NULL)
  335. + return NF_DROP;
  336. +
  337. + exp->tuple = ((struct ip_conntrack_tuple)
  338. + { { ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip, { 0 } },
  339. + { ipaddr, { .udp = { htons(port) } }, IPPROTO_UDP }});
  340. +
  341. + exp->mask = ((struct ip_conntrack_tuple)
  342. + { { 0xFFFFFFFF, { 0 } },
  343. + { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
  344. +
  345. + exp->expectfn = NULL;
  346. + exp->master = ct;
  347. +
  348. + if (ip_nat_sdp_hook)
  349. + return ip_nat_sdp_hook(pskb, ctinfo, exp, dptr);
  350. + else if (ip_conntrack_expect_related(exp) != 0) {
  351. + ip_conntrack_expect_free(exp);
  352. + return NF_DROP;
  353. + }
  354. + return NF_ACCEPT;
  355. +}
  356. +
  357. +static int sip_help(struct sk_buff **pskb,
  358. + struct ip_conntrack *ct,
  359. + enum ip_conntrack_info ctinfo)
  360. +{
  361. + unsigned int dataoff, datalen;
  362. + char *dptr;
  363. + int ret = NF_ACCEPT;
  364. + int matchoff, matchlen;
  365. + uint32_t ipaddr;
  366. + uint16_t port;
  367. +
  368. + /* No Data ? */
  369. + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
  370. + if (dataoff >= (*pskb)->len) {
  371. + DEBUGP("skb->len = %u\n", (*pskb)->len);
  372. + return NF_ACCEPT;
  373. + }
  374. +
  375. + ip_ct_refresh_acct(ct, ctinfo, NULL, sip_timeout * HZ);
  376. +
  377. + LOCK_BH(&sipbf_lock);
  378. +
  379. + if ((dataoff + (*pskb)->len - dataoff) <= skb_headlen(*pskb))
  380. + dptr = (*pskb)->data + dataoff;
  381. + else {
  382. + DEBUGP("SIP mangle in copied skbuff not supported yet.\n");
  383. + goto out;
  384. + }
  385. +
  386. + if (ip_nat_sip_hook) {
  387. + if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) {
  388. + ret = NF_DROP;
  389. + goto out;
  390. + }
  391. + }
  392. +
  393. + if ((ctinfo) >= IP_CT_IS_REPLY)
  394. + goto out;
  395. +
  396. + /* After this point NAT, could have mangled skb, so
  397. + we need to recalculate payload lenght. */
  398. + datalen = (*pskb)->len - dataoff;
  399. +
  400. + if (datalen < (sizeof("SIP/2.0 200") - 1))
  401. + goto out;
  402. +
  403. + /* RTP info only in some SDP pkts */
  404. + if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
  405. + memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
  406. + goto out;
  407. + }
  408. + /* Get ip and port address from SDP packet. */
  409. + if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
  410. + &ct_sip_hdrs[POS_CONECTION]) > 0) {
  411. +
  412. + /* We'll drop only if there are parse problems. */
  413. + if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr,
  414. + dptr + datalen) < 0) {
  415. + ret = NF_DROP;
  416. + goto out;
  417. + }
  418. + if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
  419. + &ct_sip_hdrs[POS_MEDIA]) > 0) {
  420. +
  421. + port = simple_strtoul(dptr + matchoff, NULL, 10);
  422. + if (port < 1024) {
  423. + ret = NF_DROP;
  424. + goto out;
  425. + }
  426. + ret = set_expected_rtp(pskb, ct, ctinfo,
  427. + ipaddr, port, dptr);
  428. + }
  429. + }
  430. +out: UNLOCK_BH(&sipbf_lock);
  431. + return ret;
  432. +}
  433. +
  434. +static struct ip_conntrack_helper sip[MAX_PORTS];
  435. +static char sip_names[MAX_PORTS][10];
  436. +
  437. +static void fini(void)
  438. +{
  439. + int i = 0;
  440. + for (; i < ports_c; i++) {
  441. + DEBUGP("unregistering helper for port %d\n", ports[i]);
  442. + ip_conntrack_helper_unregister(&sip[i]);
  443. + }
  444. +}
  445. +
  446. +static int __init init(void)
  447. +{
  448. + int i, ret;
  449. + char *tmpname;
  450. +
  451. + if (ports_c == 0)
  452. + ports[ports_c++] = SIP_PORT;
  453. +
  454. + for (i = 0; i < ports_c; i++) {
  455. + /* Create helper structure */
  456. + memset(&sip[i], 0, sizeof(struct ip_conntrack_helper));
  457. +
  458. + sip[i].tuple.dst.protonum = IPPROTO_UDP;
  459. + sip[i].tuple.src.u.udp.port = htons(ports[i]);
  460. + sip[i].mask.src.u.udp.port = 0xFFFF;
  461. + sip[i].mask.dst.protonum = 0xFF;
  462. + sip[i].max_expected = 1;
  463. + sip[i].timeout = 3 * 60; /* 3 minutes */
  464. + sip[i].me = THIS_MODULE;
  465. + sip[i].help = sip_help;
  466. +
  467. + tmpname = &sip_names[i][0];
  468. + if (ports[i] == SIP_PORT)
  469. + sprintf(tmpname, "sip");
  470. + else
  471. + sprintf(tmpname, "sip-%d", i);
  472. + sip[i].name = tmpname;
  473. +
  474. + DEBUGP("port #%d: %d\n", i, ports[i]);
  475. +
  476. + ret=ip_conntrack_helper_register(&sip[i]);
  477. + if (ret) {
  478. + printk("ERROR registering helper for port %d\n",
  479. + ports[i]);
  480. + fini();
  481. + return(ret);
  482. + }
  483. + }
  484. + return(0);
  485. +}
  486. +
  487. +module_init(init);
  488. +module_exit(fini);
复制代码

[ 本帖最后由 platinum 于 2006-9-25 11:08 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2006-09-25 10:46 |显示全部楼层

  1. diff -urN linux2425_jffs2/net/ipv4/netfilter/ip_nat_sip.c linux2425_jffs2/net/ipv4/netfilter/ip_nat_sip.c
  2. --- linux2425_jffs2/net/ipv4/netfilter/ip_nat_sip.c (revision 0)
  3. +++ linux2425_jffs2/net/ipv4/netfilter/ip_nat_sip.c (revision 0)
  4. @@ -0,0 +1,253 @@
  5. +/* SIP extension for UDP NAT alteration.
  6. + *
  7. + * (C) 2005 by Christian Hentschel <[email]chentschel@arnet.com.ar[/email]>
  8. + * based on RR's ip_nat_ftp.c and other modules.
  9. + *
  10. + * This program is free software; you can redistribute it and/or modify
  11. + * it under the terms of the GNU General Public License version 2 as
  12. + * published by the Free Software Foundation.
  13. + */
  14. +
  15. +#include <linux/ctype.h>
  16. +#include <linux/module.h>
  17. +#include <linux/netfilter_ipv4.h>
  18. +#include <linux/ip.h>
  19. +#include <linux/udp.h>
  20. +#include <linux/moduleparam.h>
  21. +#include <net/udp.h>
  22. +#include <linux/netfilter_ipv4/ip_nat.h>
  23. +#include <linux/netfilter_ipv4/ip_nat_helper.h>
  24. +#include <linux/netfilter_ipv4/ip_nat_rule.h>
  25. +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
  26. +#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
  27. +
  28. +MODULE_LICENSE("GPL");
  29. +MODULE_AUTHOR("Christian Hentschel <[email]chentschel@arnet.com.ar[/email]>");
  30. +MODULE_DESCRIPTION("SIP NAT helper");
  31. +
  32. +#if 0
  33. +#define DEBUGP printk
  34. +#else
  35. +#define DEBUGP(format, args...)
  36. +#endif
  37. +
  38. +extern struct sip_header_nfo ct_sip_hdrs[];
  39. +
  40. +static unsigned int mangle_sip_packet(struct sk_buff **pskb,
  41. + enum ip_conntrack_info ctinfo,
  42. + struct ip_conntrack *ct,
  43. + char **dptr, int dlen,
  44. + char *buffer, int bufflen,
  45. + struct sip_header_nfo *hnfo)
  46. +{
  47. + unsigned int matchlen, matchoff;
  48. +
  49. + if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, hnfo) <= 0)
  50. + return 0;
  51. +
  52. + if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
  53. + matchoff, matchlen, buffer, bufflen)) {
  54. + return 0;
  55. + }
  56. + /* We need to reload this. Thanks Patrick. */
  57. + *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
  58. + return 1;
  59. +}
  60. +
  61. +static unsigned int ip_nat_sip(struct sk_buff **pskb,
  62. + enum ip_conntrack_info ctinfo,
  63. + struct ip_conntrack *ct,
  64. + char **dptr)
  65. +{
  66. + char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
  67. + unsigned int bufflen, dataoff;
  68. + uint32_t ip;
  69. + uint16_t port;
  70. +
  71. + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
  72. +
  73. + if ((ctinfo) >= IP_CT_IS_REPLY) {
  74. + ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
  75. + port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
  76. + } else {
  77. + ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
  78. + port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
  79. + }
  80. + bufflen = sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(ip), ntohs(port));
  81. +
  82. + /* short packet ? */
  83. + if (((*pskb)->len - dataoff) < (sizeof("SIP/2.0") - 1))
  84. + return 0;
  85. +
  86. + /* Basic rules: requests and responses. */
  87. + if (memcmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) == 0) {
  88. +
  89. + if ((ctinfo) < IP_CT_IS_REPLY) {
  90. + mangle_sip_packet(pskb, ctinfo, ct, dptr,
  91. + (*pskb)->len - dataoff, buffer, bufflen,
  92. + &ct_sip_hdrs[POS_CONTACT]);
  93. + return 1;
  94. + }
  95. +
  96. + if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
  97. + buffer, bufflen, &ct_sip_hdrs[POS_VIA])) {
  98. + return 0;
  99. + }
  100. +
  101. + /* This search should ignore case, but later.. */
  102. + char *aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
  103. + (*pskb)->len - dataoff);
  104. + if (!aux)
  105. + return 0;
  106. +
  107. + if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
  108. + ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff))) {
  109. + return 1;
  110. + }
  111. + return mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
  112. + buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
  113. + }
  114. + if ((ctinfo) < IP_CT_IS_REPLY) {
  115. + if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
  116. + buffer, bufflen, &ct_sip_hdrs[POS_VIA])) {
  117. + return 0;
  118. + }
  119. +
  120. + /* Mangle Contact if exists only. - watch udp_nat_mangle()! */
  121. + mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
  122. + buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
  123. + return 1;
  124. + }
  125. + /* This mangle requests headers. */
  126. + return mangle_sip_packet(pskb, ctinfo, ct, dptr,
  127. + ct_sip_lnlen(*dptr, *dptr + (*pskb)->len - dataoff),
  128. + buffer, bufflen, &ct_sip_hdrs[POS_REQ_HEADER]);
  129. +}
  130. +
  131. +static int mangle_content_len(struct sk_buff **pskb,
  132. + enum ip_conntrack_info ctinfo,
  133. + struct ip_conntrack *ct,
  134. + char *dptr)
  135. +{
  136. + unsigned int dataoff, matchoff, matchlen;
  137. + char buffer[sizeof("65536")];
  138. + int bufflen;
  139. +
  140. + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
  141. +
  142. + /* Get actual SDP lenght */
  143. + if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
  144. + &matchlen, &ct_sip_hdrs[POS_SDP_HEADER]) > 0) {
  145. +
  146. + /* since ct_sip_get_info() give us a pointer passing 'v='
  147. + we need to add 2 bytes in this count. */
  148. + int c_len = (*pskb)->len - dataoff - matchoff + 2;
  149. +
  150. + /* Now, update SDP lenght */
  151. + if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
  152. + &matchlen, &ct_sip_hdrs[POS_CONTENT]) > 0) {
  153. +
  154. + bufflen = sprintf(buffer, "%u", c_len);
  155. +
  156. + return ip_nat_mangle_udp_packet(pskb, ct, ctinfo, matchoff,
  157. + matchlen, buffer, bufflen);
  158. + }
  159. + }
  160. + return 0;
  161. +}
  162. +
  163. +static unsigned int mangle_sdp(struct sk_buff **pskb,
  164. + enum ip_conntrack_info ctinfo,
  165. + struct ip_conntrack *ct,
  166. + uint32_t newip, uint16_t port,
  167. + char *dptr)
  168. +{
  169. + char buffer[sizeof("nnn.nnn.nnn.nnn")];
  170. + unsigned int dataoff, bufflen;
  171. +
  172. + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
  173. +
  174. + /* Mangle owner and contact info. */
  175. + bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
  176. + if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
  177. + buffer, bufflen, &ct_sip_hdrs[POS_OWNER])) {
  178. + return 0;
  179. + }
  180. +
  181. + if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
  182. + buffer, bufflen, &ct_sip_hdrs[POS_CONECTION])) {
  183. + return 0;
  184. + }
  185. +
  186. + /* Mangle media port. */
  187. + bufflen = sprintf(buffer, "%u", port);
  188. + if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
  189. + buffer, bufflen, &ct_sip_hdrs[POS_MEDIA])) {
  190. + return 0;
  191. + }
  192. +
  193. + return mangle_content_len(pskb, ctinfo, ct, dptr);
  194. +}
  195. +
  196. +/* So, this packet has hit the connection tracking matching code.
  197. + Mangle it, and change the expectation to match the new version. */
  198. +static unsigned int ip_nat_sdp(struct sk_buff **pskb,
  199. + enum ip_conntrack_info ctinfo,
  200. + struct ip_conntrack_expect *exp,
  201. + char *dptr)
  202. +{
  203. + struct ip_conntrack *ct = exp->master;
  204. + uint32_t newip;
  205. + uint16_t port;
  206. +
  207. + DEBUGP("ip_nat_sdp():\n");
  208. +
  209. + /* Connection will come from reply */
  210. + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
  211. +
  212. + exp->tuple.dst.ip = newip;
  213. + exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
  214. + exp->dir = IP_CT_DIR_REPLY;
  215. +
  216. + /* When you see the packet, we need to NAT it the same as the
  217. + this one. */
  218. + exp->expectfn = ip_nat_follow_master;
  219. +
  220. + /* Try to get same port: if not, try to change it. */
  221. + for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
  222. + exp->tuple.dst.u.udp.port = htons(port);
  223. + if (ip_conntrack_expect_related(exp) == 0)
  224. + break;
  225. + }
  226. +
  227. + if (port == 0) {
  228. + ip_conntrack_expect_free(exp);
  229. + return NF_DROP;
  230. + }
  231. +
  232. + if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
  233. + ip_conntrack_unexpect_related(exp);
  234. + return NF_DROP;
  235. + }
  236. + return NF_ACCEPT;
  237. +}
  238. +
  239. +static void __exit fini(void)
  240. +{
  241. + ip_nat_sip_hook = NULL;
  242. + ip_nat_sdp_hook = NULL;
  243. + /* Make sure noone calls it, meanwhile. */
  244. + synchronize_net();
  245. +}
  246. +
  247. +static int __init init(void)
  248. +{
  249. + BUG_ON(ip_nat_sip_hook);
  250. + BUG_ON(ip_nat_sdp_hook);
  251. + ip_nat_sip_hook = ip_nat_sip;
  252. + ip_nat_sdp_hook = ip_nat_sdp;
  253. + return 0;
  254. +}
  255. +
  256. +module_init(init);
  257. +module_exit(fini);
复制代码

这是经我稍微修改的sip patch for 2.4.25.应该没什么问题,模块加载也正确.这种方法就是ALG实现的方法.
但问题还是存在.

[ 本帖最后由 platinum 于 2006-9-25 11:08 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2006-09-25 11:48 |显示全部楼层
大概是,不过我也不想做ALG了,毕竟ALG要修改包头.在大量的语音传输中会影响通讯质量.还是先做一个FUll cone Nat for linux ,现在正在分析Netfilter结构,和Nat实现机制.platinum有什么相关资料介绍一下??
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP