内核协议栈 netfilter中tproxy新版本对比

 由于:linux 新内核tcp/ip协议栈中添加了 TCP_NEW_SYN_RECV; 所以 在判断sk是否为transparent 时 需要考虑其状态;

复制代码
static bool tproxy_sk_is_transparent(struct sock *sk)
{
    switch (sk->sk_state) {
    case TCP_TIME_WAIT:
        if (inet_twsk(sk)->tw_transparent)
            return true;
        break;
    case TCP_NEW_SYN_RECV:
        if (inet_rsk(inet_reqsk(sk))->no_srccheck)
            return true;
        break;
    default:
        if (inet_sk(sk)->transparent)
            return true;
    }

    sock_gen_put(sk);
    return false;
}
复制代码

 

复制代码
/**
 * tcp_make_synack - Prepare a SYN-ACK.
 * sk: listener socket
 * dst: dst entry attached to the SYNACK
 * req: request_sock pointer
 *
 * Allocate one skb and build a SYNACK packet.
 * @dst is consumed : Caller should not use it again.
 */
struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
                struct request_sock *req,
                struct tcp_fastopen_cookie *foc,
                bool attach_req)
{
    struct inet_request_sock *ireq = inet_rsk(req);
    const struct tcp_sock *tp = tcp_sk(sk);
    struct tcp_md5sig_key *md5 = NULL;
    struct tcp_out_options opts;
    struct sk_buff *skb;
    int tcp_header_size;
    struct tcphdr *th;
    u16 user_mss;
    int mss;

    skb = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
    -------------------------------
    if (attach_req) {
        skb_set_owner_w(skb, req_to_sk(req));
    } else {
        /* sk is a const pointer, because we want to express multiple
         * cpu might call us concurrently.
         * sk->sk_wmem_alloc in an atomic, we can promote to rw.
         */
        skb_set_owner_w(skb, (struct sock *)sk);
    }

-----------------------------------
}
复制代码

 

处理syn包回复syn_ack时, 设置回复报文skb结构时, 其skb->sk 可能指向req_sock 可能指向listen sk;此时和以前内核版本不一样;

所以后续处理报文以及判断此skb的transparent属性时 需要判断其sk具体指向以及数值

 

对于 sk 的释放:

复制代码
/* All sockets share common refcount, but have different destructors */
void sock_gen_put(struct sock *sk)
{
    if (!atomic_dec_and_test(&sk->sk_refcnt))
        return;

    if (sk->sk_state == TCP_TIME_WAIT)
        inet_twsk_free(inet_twsk(sk));
    else if (sk->sk_state == TCP_NEW_SYN_RECV)
        reqsk_free(inet_reqsk(sk));
    else
        sk_free(sk);
}
EXPORT_SYMBOL_GPL(sock_gen_put);

void sock_edemux(struct sk_buff *skb)
{
    sock_gen_put(skb->sk);
}

/* assign a socket to the skb -- consumes sk */
static void
nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
{
  skb_orphan(skb);
  skb->sk = sk;
  skb->destructor = sock_edemux;
}

 
复制代码

也就是需要分各种状态释放skb->sk

 

posted @   codestacklinuxer  阅读(316)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示