来自linux-2.6.36/net/ipv4/netfilter/nf_nat_helper.c

注:该代码可以移植到ebtables中使用,但需要注意struct rtable *rt结构在ebtables中是没有的。

修改UDP payload的代码:

/* Unusual, but possible case. */

static int enlarge_skb(struct sk_buff *skb, unsigned int extra)

{

if (skb->len + extra > 65535)

return 0;

if (pskb_expand_head(skb, 0, extra - skb_tailroom(skb), GFP_ATOMIC))

return 0;

return 1;

}

/* Frobs data inside this packet, which is linear. */

static void mangle_contents(struct sk_buff *skb,

unsigned int dataoff,

unsigned int match_offset,

unsigned int match_len,

const char *rep_buffer,

unsigned int rep_len)

{

unsigned char *data;

BUG_ON(skb_is_nonlinear(skb));

data = skb_network_header(skb) + dataoff;

/* move post-replacement */

memmove(data + match_offset + rep_len,

data + match_offset + match_len,

skb->tail - (skb->network_header + dataoff +

match_offset + match_len));

/* insert data from buffer */

memcpy(data + match_offset, rep_buffer, rep_len);

/* update skb info */

if (rep_len > match_len) {

pr_debug("nf_nat_mangle_packet: Extending packet by "

"%u from %u bytes\n", rep_len - match_len, skb->len);

skb_put(skb, rep_len - match_len);

} else {

pr_debug("nf_nat_mangle_packet: Shrinking packet from "

"%u from %u bytes\n", match_len - rep_len, skb->len);

__skb_trim(skb, skb->len + rep_len - match_len);

}

/* fix IP hdr checksum information */

ip_hdr(skb)->tot_len = htons(skb->len);

ip_send_check(ip_hdr(skb));

}

/* Generic function for mangling variable-length address changes of UDP packet's payload

*

* Takes care about all the nasty sequence number changes, checksumming,

* skb enlargement, ...

*

* match_offset: the payload's start point to be mangled

* match_len: the payload's length to be mangled, when 0 means insert some data into the payload

* rep_buffer: the new data to be inserted.

* rep_len: the new data's length to be inserted.

*/

static int

mangle_udp_packet(struct sk_buff *skb,

unsigned int match_offset,

unsigned int match_len,

const char *rep_buffer,

unsigned int rep_len)

{

struct rtable *rt = skb_rtable(skb);

struct iphdr *iph;

struct udphdr *udph;

int datalen, oldlen;

/* UDP helpers might accidentally mangle the wrong packet */

iph = ip_hdr(skb);

if (skb->len < iph->ihl*4 + sizeof(*udph) +

match_offset + match_len)

return 0;

if (!skb_make_writable(skb, skb->len))

return 0;

if (rep_len > match_len &&

rep_len - match_len > skb_tailroom(skb) &&

!enlarge_skb(skb, rep_len - match_len))

return 0;

iph = ip_hdr(skb);

udph = (void *)iph + iph->ihl*4;

oldlen = skb->len - iph->ihl*4;

mangle_contents(skb, iph->ihl*4 + sizeof(*udph),

match_offset, match_len, rep_buffer, rep_len);

/* update the length of the UDP packet */

datalen = skb->len - iph->ihl*4;

udph->len = htons(datalen);

/* fix udp checksum if udp checksum was previously calculated */

if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL)

return 1;

if (skb->ip_summed != CHECKSUM_PARTIAL) {

if (rt && !(rt->rt_flags & RTCF_LOCAL) &&

skb->dev->features & NETIF_F_V4_CSUM) {

skb->ip_summed = CHECKSUM_PARTIAL;

skb->csum_start = skb_headroom(skb) +

skb_network_offset(skb) +

iph->ihl * 4;

skb->csum_offset = offsetof(struct udphdr, check);

udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,

datalen, IPPROTO_UDP,

0);

} else {

udph->check = 0;

udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,

datalen, IPPROTO_UDP,

csum_partial(udph,

datalen, 0));

if (!udph->check)

udph->check = CSUM_MANGLED_0;

}

} else {

inet_proto_csum_replace2(&udph->check, skb,

htons(oldlen), htons(datalen), 1);

}

return 1;

}

修改TCP payload的方法:

/* Generic function for mangling variable-length address changes inside

* NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX

* command in FTP).

*

* Takes care about all the nasty sequence number changes, checksumming,

* skb enlargement, ...

*

* */

int __nf_nat_mangle_tcp_packet(struct sk_buff *skb,

struct nf_conn *ct,

enum ip_conntrack_info ctinfo,

unsigned int match_offset,

unsigned int match_len,

const char *rep_buffer,

unsigned int rep_len, bool adjust)

{

struct rtable *rt = skb_rtable(skb);

struct iphdr *iph;

struct tcphdr *tcph;

int oldlen, datalen;

if (!skb_make_writable(skb, skb->len))

return 0;

if (rep_len > match_len &&

rep_len - match_len > skb_tailroom(skb) &&

!enlarge_skb(skb, rep_len - match_len))

return 0;

SKB_LINEAR_ASSERT(skb);

iph = ip_hdr(skb);

tcph = (void *)iph + iph->ihl*4;

oldlen = skb->len - iph->ihl*4;

mangle_contents(skb, iph->ihl*4 + tcph->doff*4,

match_offset, match_len, rep_buffer, rep_len);

datalen = skb->len - iph->ihl*4;

if (skb->ip_summed != CHECKSUM_PARTIAL) {

if (!(rt->rt_flags & RTCF_LOCAL) &&

skb->dev->features & NETIF_F_V4_CSUM) {

skb->ip_summed = CHECKSUM_PARTIAL;

skb->csum_start = skb_headroom(skb) +

skb_network_offset(skb) +

iph->ihl * 4;

skb->csum_offset = offsetof(struct tcphdr, check);

tcph->check = ~tcp_v4_check(datalen,

iph->saddr, iph->daddr, 0);

} else {

tcph->check = 0;

tcph->check = tcp_v4_check(datalen,

iph->saddr, iph->daddr,

csum_partial(tcph,

datalen, 0));

}

} else

inet_proto_csum_replace2(&tcph->check, skb,

htons(oldlen), htons(datalen), 1);

if (adjust && rep_len != match_len)

nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq,

(int)rep_len - (int)match_len);

return 1;

}

linux tcp header更改,Linux Netfilter中修改TCP/UDP Payload的方法相关推荐

  1. linux环境配置以后生效,Linux中修改环境变量及生效方法

    Linux中修改环境变量及生效方法 在/etc/profile文件中添加变量[对所有用户生效(永久的)] 用VI在文件/etc/profile文件中增加变量,该变量将会对Linux下所有用户有效,并且 ...

  2. linux环境变量生效方式,Linux中修改环境变量及生效方法

    Linux中修改环境变量及生效方法 方法一: 在/etc/profile文件中添加变量[对所有用户生效(永久的)] 用VI在文件/etc/profile文件中增加变量,该变量将会对Linux下所有用户 ...

  3. python写错了怎么更改-Python中修改字符串的四种方法

    在Python中,字符串是不可变类型,即无法直接修改字符串的某一位字符. 因此改变一个字符串的元素需要新建一个新的字符串. 常见的修改方法有以下4种. 方法1:将字符串转换成列表后修改值,然后用joi ...

  4. python字符串中某个字符修改_Python中修改字符串的四种方法

    在Python中,字符串是不可变类型,即无法直接修改字符串的某一位字符. 因此改变一个字符串的元素需要新建一个新的字符串. 常见的修改方法有以下4种. 方法1:将字符串转换成列表后修改值,然后用joi ...

  5. 单一修改高程值lisp_浅谈AutoCAD中修改高程的四种方法

    浅谈 AutoCAD 中修改高程的四种方法 摘 要: 在使用 AutoCAD 进行数字化成图工作中,经常遇到线划的标高不为零,及高程点的值与实地不符,需要对其进行修改等情况,结合实 际工作经验,简单介 ...

  6. word涂改涂掉图片_怎么在word中修改图片的两种方法

    有时我们插入的图片只有一部分是我们想要的,那就需要我们将这一部分裁剪出来,word本身就可以方便快捷的对图片进行裁剪,那么下面就由学习啦小编给大家分享下在word中修改图片的技巧,希望能帮助到您. 在 ...

  7. linux内核 header.s,Linux启动代码header.S研究

    Linux内核从2.4升级到2.6之后,内核的引导过程发生了许多变化,现在研究一下Linux内核2.6版本的主要引导过程. (参考资料: 1.<深入理解Linux内核>附录A: 2.Lin ...

  8. linux mint 18.3浏览器,在Linux Mint 19/Ubuntu 18.04中安装Tor Browser浏览器的方法

    本文介绍在Linux Mint 19/Ubuntu 18.04系统中安装Tor Browser浏览器的方法,本文不使用Tor的默认Ubuntu存储库,因为它们包含旧版本的Tor. 一.添加Tor存储库 ...

  9. b宝塔 centos端口更改_BT宝塔面板修改默认8888端口的方法

    BT宝塔面板默认的端口为8888号端口,安全起见,用户可以自定义更改默认的8888端口号,环境吧分享BT宝塔面板修改默认端口号的方法: BT宝塔面板修改默认端口号的方法 更改8888号默认端口号的方法 ...

最新文章

  1. There is no isNullOrEmpty for collections in Guawa
  2. bose耳机信号断续_最便宜的TWS主动降噪耳机 233621 Zen 4400字深度评测
  3. figure diagram illustrate exemplify profile
  4. django学习第77天Django框架ORM
  5. turtle python tkinter_【案例】 什么?idle 中竟然有内置 turtle 样例?(paint)
  6. leetcode 两数相加
  7. 我的第一次Pascal程序
  8. 课堂练习 组合数据练习
  9. codevs 1683 车厢重组
  10. MySQL8.0.22解压安装教程
  11. 基于python flask的网上商城源码 mysql数据库
  12. 数据恢复——在Windows 10中恢复永久删除的文件的5种方法
  13. 看他如何做到4年2个博士学位,做研究、出书挣钱两不误。
  14. 图像拼接(八):拼接多幅图像+Matlab实现+Stanford Open Course
  15. 2016年VB图书253本推荐
  16. docker部署微服务项目
  17. samba服务器讲解
  18. 字符串根据字节长度进行截取并展示选中效果——js字符串获取字节长度
  19. Gephi中的统计算法学习
  20. ThingsBoard添加高德地图

热门文章

  1. python 动态规划 数塔_数塔问题,简单的动态规划算法
  2. java mysql show status_Java 能不能执行mysql 中的show master status 命令
  3. Android 向右滑返回,退出当前activity
  4. Android修改项目包名
  5. csdn markdown 编辑器开启
  6. centos7 python3.6编译安装
  7. SharpZipLib压缩解压
  8. 用conda安装虚拟的R环境
  9. dw替换多个html标签,DW查找替换的技巧
  10. 服务器imm口加载硬盘,ibm x3250 M4如何进IMM(远程管理口)