日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

一個(gè)VPN項(xiàng)目(Vtun)源碼分析

系統(tǒng) 3521 0
      
          1
      
      
        /*
      
      
        ****************************************


      
      
          2
      
      
        * Name        : Vtun 源碼詳細(xì)分析


      
      
          3
      
      
        * Version     : 3.0.3


      
      
          4
      
      
        * Date        : Jan. 22, 2014


      
      
          5
      
      
        * Author      : lucas


      
      
          6
      
      
        * Email       : lucasysfeng@gmail.com


      
      
          7
      
      
        * Blog        : 
      
      
        http://www.cnblogs.com/lucasysfeng/
      
      
          8
      
      
        * Description : 1.Vtun是一個(gè)短小精悍的開源VPN項(xiàng)目,


      
      
          9
      
      
        *                 這里分析了其客戶端和服務(wù)器的源碼。


      
      
         10
      
      
        *               2.vtun源碼可以從下面網(wǎng)址下載


      
      
         11
      
      
        *                 
      
      
        http://vtun.sourceforge.net/
      
      
         12
      
      
        ****************************************
      
      
        */
      
      
         13
      
      
         14
      
      
         15
      
      
        /*
      
      
        ********************************************** client端代碼執(zhí)行基本流程分析 ***********************************************
      
      
        */
      
      
         16
      
      
        /*
      
      
        ***************************************************************


      
      
         17
      
      
        *原型:int main(int argc, char* argv[], char* env[]);


      
      
         18
      
      
        *功能:初始化操作,確定是client端還是server端。


      
      
         19
      
      
        *下一步:根據(jù)命令行參數(shù)選擇執(zhí)行client或者server分支,先分析client。


      
      
         20
      
      
        ****************************************************************
      
      
        */
      
      
         21
      
      
        int
      
       main(
      
        int
      
       argc, 
      
        char
      
       *argv[], 
      
        char
      
       *
      
        env[])


      
      
         22
      
      
        {


      
      
         23
      
      
            ......


      
      
         24
      
           ......
      
        //
      
      
        初始化vtun結(jié)構(gòu)體。
      
      
         25
      
      
        while
      
       ((opt = getopt(argc, argv, 
      
        "
      
      
        misf:P:L:t:npq
      
      
        "
      
      )) !=  EOF) 
      
        //
      
      
        獲取命令行參數(shù)并進(jìn)行相應(yīng)操作。
      
      
         26
      
      
            {


      
      
         27
      
      
                ......


      
      
         28
      
      
            }


      
      
         29
      
           reread_config(
      
        0
      
      );                                            
      
        //
      
      
        讀配置文件。
      
      
         30
      
      
            ......


      
      
         31
      
           clear_nat_hack_flags(svr);                                   
      
        //
      
      
        清除另一方的nat_hack標(biāo)志。
      
      
         32
      
      
        if
      
       (!svr)                                                    
      
        //
      
      
        根據(jù)命令行參數(shù)進(jìn)行客戶端配置。
      
      
         33
      
      
            {


      
      
         34
      
      
                ......


      
      
         35
      
               hst = argv[optind++];                                    
      
        //
      
      
        vtund server [ip]的第二個(gè)參數(shù)給hst,這個(gè)參數(shù)是服務(wù)器給客戶端定義的名字。
      
      
         36
      
               host = find_host(hst);                                   
      
        //
      
      
        hst是命令行參數(shù),host是配置文件中的對應(yīng)該參數(shù)的會(huì)話信息。
      
      
         37
      
      
                ......


      
      
         38
      
      
            }


      
      
         39
      
           vtun.svr_name = strdup(argv[optind]);                        
      
        //
      
      
        vtund server [ip]的ip給vtun.srv_name
      
      
         40
      
           ......                                                       
      
        //
      
      
        如果vtun結(jié)構(gòu)體的一些成員沒有被初試話,則賦予默認(rèn)值。
      
      
         41
      
      
        switch
      
       (vtun.svr_type)                                       
      
        //
      
      
        判斷vtun的類型,VTUN_STAND_ALONE VTUN_INETD.
      
      
         42
      
      
            {


      
      
         43
      
      
                ......


      
      
         44
      
      
            }


      
      
         45
      
      
        if
      
       (daemon)                                                  
      
        //
      
      
        是否要?jiǎng)?chuàng)建守護(hù)進(jìn)程
      
      
         46
      
      
            {


      
      
         47
      
      
        if
      
       (dofork && fork())                                    
      
        //
      
      
        當(dāng)命令行設(shè)置為超級(jí)守護(hù)進(jìn)程時(shí)不執(zhí)行該操作。
      
      
         48
      
      
                    ...


      
      
         49
      
      
            }


      
      
         50
      
      
        if
      
      
         (svr)


      
      
         51
      
      
            {


      
      
         52
      
               memset(&sa, 
      
        0
      
      , 
      
        sizeof
      
      (sa));                              
      
        //
      
      
        掛起時(shí)讀取配置文件。
      
      
         53
      
               sa.sa_handler =
      
         reread_config;


      
      
         54
      
               sigaction(SIGHUP, &
      
        sa, NULL);


      
      
         55
      
               init_title(argc, argv, env, 
      
        "
      
      
        vtund[s]: 
      
      
        "
      
      
        );


      
      
         56
      
      
         57
      
      
        if
      
       (vtun.svr_type ==
      
         VTUN_STAND_ALONE)


      
      
         58
      
                   write_pid();                                         
      
        //
      
      
        將當(dāng)前pid寫入文件中
      
      
         59
      
      
         60
      
               server(sock);                                            
      
        //
      
      
        執(zhí)行服務(wù)器操作
      
      
         61
      
      
            }


      
      
         62
      
      
        else
      
      
         63
      
      
            {


      
      
         64
      
                init_title(argc, argv, env, 
      
        "
      
      
        vtund[c]: 
      
      
        "
      
      
        );


      
      
         65
      
                client(host);                                           
      
        //
      
      
        執(zhí)行客戶端操作,host就是從配置文件讀取出的對應(yīng)命令行參數(shù)會(huì)話名的信息。
      
      
         66
      
      
            }


      
      
         67
      
      
            ......


      
      
         68
      
      
        }


      
      
         69
      
      
         70
      
      
         71
      
      
        /*
      
      
        ***********************************************************


      
      
         72
      
      
        *原型:void client(struct vtun_host *host);


      
      
         73
      
      
        *參數(shù):host是從配置文件中讀出某個(gè)會(huì)話名所包含的信息。


      
      
         74
      
      
        *功能:建立socket以及bind、connect、select等,認(rèn)證暨建立隧道。


      
      
         75
      
      
        *下一步:認(rèn)證auth_client(s, host)后再執(zhí)行tunnel(host)即開啟隧道。


      
      
         76
      
      
        ************************************************************
      
      
        */
      
      
         77
      
      
        void
      
       client(
      
        struct
      
       vtun_host *host)                                        
      
        //
      
      
        host參數(shù)是main函數(shù)中傳遞的配置文件中的會(huì)話信息。
      
      
         78
      
      
        {


      
      
         79
      
      
            ......


      
      
         80
      
           ......                                                                 
      
        //
      
      
        結(jié)束,掛起等信號(hào)處理函數(shù)。
      
      
         81
      
      
        while
      
       ((!client_term) || (client_term ==
      
         VTUN_SIG_HUP))


      
      
         82
      
      
            {


      
      
         83
      
      
        if
      
       (reconnect && (client_term != VTUN_SIG_HUP)) { ...... }         
      
        //
      
      
        重連
      
      
         84
      
      
                ......


      
      
         85
      
      
        if
      
       (server_addr(&svr_addr, host) < 
      
        0
      
      )    
      
        continue
      
      ;                 
      
        //
      
      
         Set server address
      
      
         86
      
      
        if
      
       (local_addr(&my_addr, host, 
      
        0
      
      ) < 
      
        0
      
      )    
      
        continue
      
      ;                
      
        //
      
      
         Set local address
      
      
         87
      
      
        if
      
       ((s = socket(AF_INET, SOCK_STREAM, 
      
        0
      
      )) == -
      
        1
      
      ) { ...... }          
      
        //
      
      
        建立socket套接字
      
      
         88
      
               opt = 
      
        1
      
      
        ;


      
      
         89
      
               setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, 
      
        sizeof
      
      (opt));        
      
        //
      
      
         Required when client is forced to bind to specific port
      
      
         90
      
      
        if
      
       (bind(s, (
      
        struct
      
       sockaddr *)&my_addr, 
      
        sizeof
      
      (my_addr))){.....}  
      
        //
      
      
        bind
      
      
         91
      
               host->spd_in = host->spd_out = 
      
        0
      
      
        ;


      
      
         92
      
               host->flags &= VTUN_CLNT_MASK;                                     
      
        //
      
      
        Clear speed and flags which will be supplied by server.
      
      
         93
      
      
                io_init();


      
      
         94
      
      
                ......


      
      
         95
      
      
         96
      
      
        if
      
       (connect_t(s,(
      
        struct
      
       sockaddr *) &svr_addr, host->
      
        timeout))


      
      
         97
      
      
                {


      
      
         98
      
      
                    .....


      
      
         99
      
      
                }


      
      
        100
      
      
        else
      
      
        101
      
      
                {


      
      
        102
      
      
        if
      
       (auth_client(s, host))                                      
      
        //
      
      
        認(rèn)證,也就是隧道建立過程
      
      
        103
      
      
                    {


      
      
        104
      
      
                        ...


      
      
        105
      
                       client_term = tunnel(host);                                
      
        //
      
      
        開啟隧道,host是配置文件相應(yīng)會(huì)話信息。
      
      
        106
      
      
                        ...


      
      
        107
      
      
                    }


      
      
        108
      
      
        else
      
      
        109
      
      
                    {


      
      
        110
      
                       ......                                                     
      
        //
      
      
        認(rèn)證失敗
      
      
        111
      
      
                    }


      
      
        112
      
      
                }


      
      
        113
      
      
                close(s);


      
      
        114
      
               free_sopt(&host->
      
        sopt);


      
      
        115
      
           }
      
        //
      
      
        end while
      
      
        116
      
      
            ......


      
      
        117
      
      
        }


      
      
        118
      
      
        119
      
      
        /*
      
      
        ***************************************************************************


      
      
        120
      
      
        *補(bǔ)充:在執(zhí)行tunnel(host)前先來看看上面client函數(shù)中的connect_t函數(shù)。


      
      
        121
      
      
        *原型:int connect_t(int s, struct sockaddr *svr, time_t timeout);


      
      
        122
      
      
        *參數(shù):s是client中建立的套接字描述符。


      
      
        123
      
      
        *功能:與服務(wù)器建立連接。


      
      
        124
      
      
        ****************************************************************************
      
      
        */
      
      
        125
      
      
        int
      
       connect_t(
      
        int
      
       s, 
      
        struct
      
       sockaddr *
      
        svr, time_t timeout)


      
      
        126
      
      
        {


      
      
        127
      
      
        #if
      
       defined(VTUN_SOCKS) && VTUN_SOCKS == 2


      
        128
      
      
        /*
      
      
         Some SOCKS implementations don't support


      
      
        129
      
      
              * non blocking connect 
      
      
        */
      
      
        130
      
      
        return
      
       connect(s, svr, 
      
        sizeof
      
      (
      
        struct
      
      
         sockaddr));


      
      
        131
      
      
        #else
      
      
        132
      
           sock_flags =
      
         fcntl(s, F_GETFL);


      
      
        133
      
      
        if
      
       (fcntl(s, F_SETFL, O_NONBLOCK) < 
      
        0
      
      )...
      
        //
      
      
        設(shè)置s為非阻塞?
      
      
        134
      
      
        if
      
       (connect(s, svr, 
      
        sizeof
      
      (
      
        struct
      
       sockaddr)) < 
      
        0
      
       && errno !=
      
         EINPROGRESS)...


      
      
        135
      
      
            ......


      
      
        136
      
      
        if
      
       (
      
        select
      
      (s+
      
        1
      
      , NULL, &fdset, NULL, timeout?&tv:NULL) > 
      
        0
      
      
        )


      
      
        137
      
      
            {


      
      
        138
      
      
                ...


      
      
        139
      
               getsockopt(s, SOL_SOCKET, SO_ERROR, &errno, &l);
      
        //
      
      
        ?
      
      
        140
      
      
            }


      
      
        141
      
      
        else
      
      
        142
      
      
            {


      
      
        143
      
               errno =
      
         ETIMEDOUT;


      
      
        144
      
      
                fcntl(s, F_SETFL, sock_flags);


      
      
        145
      
      
                ...


      
      
        146
      
      
            }


      
      
        147
      
      
        #endif
      
      
        148
      
       }
      
        //
      
      
        end connect_t
      
      
        149
      
      
        150
      
      
        /*
      
      
        ************************************************************************


      
      
        151
      
      
        *補(bǔ)充:在執(zhí)行tunnel(host)前再來看看上面client函數(shù)中的auth_client.


      
      
        152
      
      
        *原型:int auth_client(int fd, struct vtun_host *host);


      
      
        153
      
      
        *參數(shù):fd是client端創(chuàng)建的套接字描述符,host是配置文件中某個(gè)會(huì)話所包含的信息


      
      
        154
      
      
        *功能:認(rèn)證過程,也是隧道建立過程。


      
      
        155
      
      
        *************************************************************************
      
      
        */
      
      
        156
      
      
        int
      
       auth_client(
      
        int
      
       fd, 
      
        struct
      
       vtun_host *
      
        host)


      
      
        157
      
      
        {


      
      
        158
      
      
            ......


      
      
        159
      
           stage = ST_INIT;                                                  
      
        //
      
      
        #define ST_INIT  0
      
      
        160
      
      
        while
      
       (readn_t(fd, buf, VTUN_MESG_SIZE, vtun.timeout) > 
      
        0
      
      )        
      
        //
      
      
        讀取服務(wù)器發(fā)來認(rèn)證信息。
      
      
        161
      
      
            {


      
      
        162
      
               buf[
      
        sizeof
      
      (buf)-
      
        1
      
      ]=
      
        '
      
      
        \0
      
      
        '
      
      
        ;


      
      
        163
      
      
        switch
      
      
         (stage)


      
      
        164
      
      
                {


      
      
        165
      
      
        case
      
      
         ST_INIT:


      
      
        166
      
      
        if
      
       (!strncmp(buf,
      
        "
      
      
        VTUN
      
      
        "
      
      ,
      
        4
      
      
        ))


      
      
        167
      
      
                        {


      
      
        168
      
                           stage =
      
         ST_HOST;


      
      
        169
      
                           print_p(fd,
      
        "
      
      
        HOST: %s\n
      
      
        "
      
      ,host->host);              
      
        //
      
      
        print_p向server發(fā)送HOST:[host]。
      
      
        170
      
      
        continue
      
      
        ;


      
      
        171
      
      
                        }


      
      
        172
      
      
        break
      
      
        ;


      
      
        173
      
      
        case
      
      
         ST_HOST:


      
      
        174
      
      
        if
      
       (!strncmp(buf, 
      
        "
      
      
        OK
      
      
        "
      
      , 
      
        2
      
      ) && cs2cl(buf, chal))       
      
        //
      
      
        接收到請求發(fā)送密碼信息 OK CHAL:[chal]
      
      
        175
      
      
                        {


      
      
        176
      
                           stage =
      
         ST_CHAL;


      
      
        177
      
                           encrypt_chal(chal, host->
      
        passwd);


      
      
        178
      
                           print_p(fd,
      
        "
      
      
        CHAL: %s\n
      
      
        "
      
      , cl2cs(chal));            
      
        //
      
      
        發(fā)送配置文件中本次會(huì)話密碼CHAL:[chal]
      
      
        179
      
      
        continue
      
      
        ;


      
      
        180
      
      
                        }


      
      
        181
      
      
        break
      
      
        ;


      
      
        182
      
      
        case
      
      
         ST_CHAL:


      
      
        183
      
      
        if
      
       (!strncmp(buf, 
      
        "
      
      
        OK
      
      
        "
      
      , 
      
        2
      
      ) && cf2bf(buf, host))       
      
        //
      
      
        接收到OK FLAGS:[host]認(rèn)證成功信息
      
      
        184
      
                           success = 
      
        1
      
      
        ;


      
      
        185
      
      
        break
      
      
        ;


      
      
        186
      
      
                 }


      
      
        187
      
      
        break
      
      
        ;


      
      
        188
      
            }
      
        //
      
      
        end while
      
      
        189
      
      
        return
      
      
         success;


      
      
        190
      
      
        }


      
      
        191
      
      
        192
      
      
        /*
      
      
        ************************************************************************


      
      
        193
      
      
        *原型:int tunnel(strucnt vtun_host* host);


      
      
        194
      
      
        *參數(shù):host是配置文件中某個(gè)會(huì)話所包含的信息


      
      
        195
      
      
        *功能:開啟隧道即初試話設(shè)備讀寫函數(shù),初始化封裝后發(fā)送接收所用協(xié)議。


      
      
        196
      
      
        *下一步:linkfd(host);


      
      
        197
      
      
        *************************************************************************
      
      
        */
      
      
        198
      
      
        int
      
       tunnel(
      
        struct
      
       vtun_host *
      
        host)


      
      
        199
      
      
        {


      
      
        200
      
      
            ......


      
      
        201
      
      
        if
      
       ((host->persist == VTUN_PERSIST_KEEPIF) && (host->loc_fd >= 
      
        0
      
      ))
      
        //
      
      
        接口是否已經(jīng)打開
      
      
        202
      
           interface_already_open = 
      
        1
      
      
        ;


      
      
        203
      
      
        if
      
       (host->dev){...}                                               
      
        //
      
      
        判斷虛擬設(shè)備類型
      
      
        204
      
      
        if
      
       (!interface_already_open)                                      
      
        //
      
      
        虛擬網(wǎng)卡沒有打開,則打開之
      
      
        205
      
      
        206
      
      
                ...


      
      
        207
      
      
        switch
      
       (host->flags &
      
         VTUN_TYPE_MASK)


      
      
        208
      
      
                {


      
      
        209
      
      
                    ...


      
      
        210
      
      
        case
      
      
         VTUN_TUN:


      
      
        211
      
      
        if
      
       ((fd[
      
        0
      
      ]=tun_open(dev)) < 
      
        0
      
      )                        
      
        //
      
      
        打開虛擬網(wǎng)卡,獲取描述符
      
      
        212
      
      
                        {


      
      
        213
      
                           vtun_syslog(LOG_ERR,
      
        "
      
      
        Can't allocate tun device %s. %s(%d)
      
      
        "
      
      
        , dev, strerror(errno), errno);


      
      
        214
      
      
        return
      
       -
      
        1
      
      
        ;


      
      
        215
      
      
                        }


      
      
        216
      
      
        break
      
      
        ;


      
      
        217
      
      
                }


      
      
        218
      
               host->loc_fd = fd[
      
        0
      
      ];                                         
      
        //
      
      
        虛擬設(shè)備文件描述符存在host->loc_fd中
      
      
        219
      
      
            }


      
      
        220
      
      
        switch
      
       (host->flags & VTUN_PROT_MASK)                             
      
        //
      
      
        初始化協(xié)議,tcp還是udp
      
      
        221
      
      
            {


      
      
        222
      
      
                ......


      
      
        223
      
      
        case
      
      
         VTUN_UDP:


      
      
        224
      
      
        if
      
       ((opt = udp_session(host)) == -
      
        1
      
      ){.....}               
      
        //
      
      
        進(jìn)行udp的socket創(chuàng)建等操作
      
      
        225
      
                   proto_write =
      
         udp_write;


      
      
        226
      
                   proto_read =
      
         udp_read;


      
      
        227
      
      
            }


      
      
        228
      
      
        switch
      
       ((pid = fork())){...}                                      
      
        //
      
      
        建立子進(jìn)程
      
      
        229
      
      
        switch
      
       (host->flags & VTUN_TYPE_MASK)                             
      
        //
      
      
        根據(jù)虛擬設(shè)備類型,選擇相應(yīng)虛擬設(shè)備讀寫方式
      
      
        230
      
      
            {


      
      
        231
      
      
                 .....


      
      
        232
      
      
        case
      
      
         VTUN_TUN:


      
      
        233
      
                    set_title(
      
        "
      
      
        %s tun %s
      
      
        "
      
      , host->
      
        host, dev);


      
      
        234
      
                    dev_read  =
      
         tun_read;


      
      
        235
      
                    dev_write =
      
         tun_write;


      
      
        236
      
      
        break
      
      
        ;


      
      
        237
      
      
             }


      
      
        238
      
            opt =
      
         linkfd(host);


      
      
        239
      
      
             .......


      
      
        240
      
      
        }


      
      
        241
      
      
        242
      
      
        /*
      
      
        ************************************************************************


      
      
        243
      
      
        *補(bǔ)充:在linkfd之前,我們先來看看tunnel函數(shù)中udp_session.


      
      
        244
      
      
        *原型:int udp_session(struct vtun_host *host);


      
      
        245
      
      
        *參數(shù):host是配置文件中某個(gè)會(huì)話所包含的信息。


      
      
        246
      
      
        *功能:udp socket的創(chuàng)建、bind、connect等。


      
      
        247
      
      
        *************************************************************************
      
      
        */
      
      
        248
      
      
        int
      
       udp_session(
      
        struct
      
       vtun_host *
      
        host)


      
      
        249
      
      
        {


      
      
        250
      
      
        struct
      
      
         sockaddr_in saddr;


      
      
        251
      
      
        short
      
      
         port;


      
      
        252
      
      
        int
      
      
         s, opt;


      
      
        253
      
      
        extern
      
      
        int
      
      
         is_rmt_fd_connected;


      
      
        254
      
      
        255
      
      
        if
      
       ((s = socket(AF_INET, SOCK_DGRAM, 
      
        0
      
      )) ==  -
      
        1
      
      
        )


      
      
        256
      
      
            {


      
      
        257
      
               vtun_syslog(LOG_ERR,
      
        "
      
      
        Can't create socket
      
      
        "
      
      
        );


      
      
        258
      
      
        return
      
       -
      
        1
      
      
        ;


      
      
        259
      
      
            }


      
      
        260
      
      
        261
      
           opt = 
      
        1
      
      
        ;


      
      
        262
      
           setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, 
      
        sizeof
      
      
        (opt));


      
      
        263
      
      
        264
      
      
        /*
      
      
         Set local address and port 
      
      
        */
      
      
        265
      
           local_addr(&saddr, host, 
      
        1
      
      
        );


      
      
        266
      
      
        if
      
       (bind(s, (
      
        struct
      
       sockaddr *) &saddr, 
      
        sizeof
      
      
        (saddr)))


      
      
        267
      
      
            {


      
      
        268
      
               vtun_syslog(LOG_ERR, 
      
        "
      
      
        Can't bind to the socket
      
      
        "
      
      
        );


      
      
        269
      
      
        return
      
       -
      
        1
      
      
        ;


      
      
        270
      
      
            }


      
      
        271
      
      
        272
      
           opt = 
      
        sizeof
      
      
        (saddr);


      
      
        273
      
      
        if
      
       (getsockname(s, (
      
        struct
      
       sockaddr *) &saddr, &
      
        opt))


      
      
        274
      
      
            {


      
      
        275
      
               vtun_syslog(LOG_ERR, 
      
        "
      
      
        Can't get socket name
      
      
        "
      
      
        );


      
      
        276
      
      
        return
      
       -
      
        1
      
      
        ;


      
      
        277
      
      
            }


      
      
        278
      
      
        279
      
      
        /*
      
      
         Write port of the new UDP socket 
      
      
        */
      
      
        280
      
           port =
      
         saddr.sin_port;


      
      
        281
      
      
        if
      
       (write_n(host->rmt_fd, (
      
        char
      
       *) &port, 
      
        sizeof
      
      (
      
        short
      
      )) < 
      
        0
      
      
        )


      
      
        282
      
      
            {


      
      
        283
      
               vtun_syslog(LOG_ERR, 
      
        "
      
      
        Can't write port number
      
      
        "
      
      
        );


      
      
        284
      
      
        return
      
       -
      
        1
      
      
        ;


      
      
        285
      
      
            }


      
      
        286
      
           host->sopt.lport =
      
         htons(port);


      
      
        287
      
      
        288
      
      
        /*
      
      
         Read port of the other's end UDP socket 
      
      
        */
      
      
        289
      
      
        if
      
       (readn_t(host->rmt_fd, &port, 
      
        sizeof
      
      (
      
        short
      
      ), host->timeout) < 
      
        0
      
      
        )


      
      
        290
      
      
            {


      
      
        291
      
               vtun_syslog(LOG_ERR, 
      
        "
      
      
        Can't read port number %s
      
      
        "
      
      
        , strerror(errno));


      
      
        292
      
      
        return
      
       -
      
        1
      
      
        ;


      
      
        293
      
      
            }


      
      
        294
      
      
        295
      
           opt = 
      
        sizeof
      
      
        (saddr);


      
      
        296
      
      
        if
      
       (getpeername(host->rmt_fd, (
      
        struct
      
       sockaddr *) &saddr, &
      
        opt))


      
      
        297
      
      
            {


      
      
        298
      
               vtun_syslog(LOG_ERR, 
      
        "
      
      
        Can't get peer name
      
      
        "
      
      
        );


      
      
        299
      
      
        return
      
       -
      
        1
      
      
        ;


      
      
        300
      
      
            }


      
      
        301
      
      
        302
      
            saddr.sin_port =
      
         port;


      
      
        303
      
      
        304
      
      
        /*
      
      
         if the config says to delay the UDP connection, we wait for an


      
      
        305
      
      
             incoming packet and then force a connection back.  We need to


      
      
        306
      
      
             put this here because we need to keep that incoming triggering


      
      
        307
      
      
             packet and pass it back up the chain. 
      
      
        */
      
      
        308
      
      
        309
      
      
        if
      
      
         (VTUN_USE_NAT_HACK(host))


      
      
        310
      
                 is_rmt_fd_connected = 
      
        0
      
      
        ;


      
      
        311
      
      
        else
      
      
        312
      
      
             {


      
      
        313
      
      
        if
      
       (connect(s, (
      
        struct
      
       sockaddr *)&saddr, 
      
        sizeof
      
      
        (saddr)))


      
      
        314
      
      
                  {


      
      
        315
      
                     vtun_syslog(LOG_ERR,
      
        "
      
      
        Can't connect socket
      
      
        "
      
      
        );


      
      
        316
      
      
        return
      
       -
      
        1
      
      
        ;


      
      
        317
      
      
                  }


      
      
        318
      
                 is_rmt_fd_connected = 
      
        1
      
      
        ;


      
      
        319
      
      
             }


      
      
        320
      
      
        321
      
            host->sopt.rport =
      
         htons(port);


      
      
        322
      
      
        323
      
      
        /*
      
      
         Close TCP socket and replace with UDP socket 
      
      
        */
      
      
        324
      
            close(host->
      
        rmt_fd);


      
      
        325
      
            host->rmt_fd = s;                                                
      
        //
      
      
        將TCP套接字替換為UDP套接字。
      
      
        326
      
      
        327
      
            vtun_syslog(LOG_INFO,
      
        "
      
      
        UDP connection initialized
      
      
        "
      
      
        );


      
      
        328
      
      
        return
      
      
         s;


      
      
        329
      
      
        }


      
      
        330
      
      
        331
      
      
        /*
      
      
        ************************************************************************


      
      
        332
      
      
        *原型:int linkfd(struct vtun_host *host);


      
      
        333
      
      
        *參數(shù):host是配置文件中某個(gè)會(huì)話所包含的信息。


      
      
        334
      
      
        *功能:初始化加密解密壓縮解壓模塊。


      
      
        335
      
      
        *下一步:虛擬網(wǎng)卡讀寫以及數(shù)據(jù)的接收發(fā)送lfd_linker();


      
      
        336
      
      
        *************************************************************************
      
      
        */
      
      
        337
      
      
        int
      
       linkfd(
      
        struct
      
       vtun_host *
      
        host)


      
      
        338
      
      
        {


      
      
        339
      
      
            ......


      
      
        340
      
           lfd_host =
      
         host;


      
      
        341
      
           old_prio = getpriority(PRIO_PROCESS, 
      
        0
      
      ); 
      
        //
      
      
        取得進(jìn)程優(yōu)先級(jí)
      
      
        342
      
           setpriority(PRIO_PROCESS, 
      
        0
      
      
        , LINKFD_PRIO);


      
      
        343
      
           ...... 
      
        //
      
      
        Build modules stack加密壓縮等。
      
      
        344
      
           ...... 
      
        //
      
      
        結(jié)束進(jìn)程等信號(hào)處理函數(shù)。
      
      
        345
      
      
            io_init();


      
      
        346
      
           lfd_linker(); 
      
        //
      
      
        虛擬網(wǎng)卡讀寫,封裝解封以及發(fā)送。
      
      
        347
      
           ...... 
      
        //
      
      
        鬧鐘信號(hào)等。
      
      
        348
      
      
        }


      
      
        349
      
      
        350
      
      
        /*
      
      
        ************************************************************************


      
      
        351
      
      
        *原型:int lfd_linker(void)


      
      
        352
      
      
        *功能:虛擬網(wǎng)卡讀寫以及數(shù)據(jù)的接收發(fā)送lfd_linker();


      
      
        353
      
      
        *下一步:結(jié)束。


      
      
        354
      
      
        *************************************************************************
      
      
        */
      
      
        355
      
      
        int
      
       lfd_linker(
      
        void
      
      
        )


      
      
        356
      
      
        {


      
      
        357
      
      
        int
      
       fd1 = lfd_host->rmt_fd;                                       
      
        //
      
      
        fd1是網(wǎng)絡(luò)套接字描述符,也就是最后封裝發(fā)送的那個(gè)套接字描述符。
      
      
        358
      
      
        int
      
       fd2 = lfd_host->loc_fd;                                       
      
        //
      
      
        fd2是虛擬網(wǎng)卡設(shè)備文件描述符。
      
      
        359
      
      
            ......


      
      
        360
      
      
        /*
      
      
         Delay sending of first UDP packet over broken NAT routers


      
      
        361
      
      
             because we will probably be disconnected.  Wait for the remote


      
      
        362
      
      
             end to send us something first, and use that connection. 
      
      
        */
      
      
        363
      
      
        if
      
       (!VTUN_USE_NAT_HACK(lfd_host)) 
      
        //
      
      
        ?
      
      
        364
      
      
            proto_write(fd1, buf, VTUN_ECHO_REQ);


      
      
        365
      
      
            ......


      
      
        366
      
      
        while
      
       (!linker_term)                                              
      
        //
      
      
        while循環(huán)體從虛擬網(wǎng)卡讀數(shù)據(jù)后發(fā)送;將接收的數(shù)據(jù)寫入虛擬網(wǎng)卡。
      
      
        367
      
      
            {


      
      
        368
      
      
                ......


      
      
        369
      
               FD_ZERO(&fdset);                                              
      
        //
      
      
        等待數(shù)據(jù)
      
      
        370
      
               FD_SET(fd1, &
      
        fdset);


      
      
        371
      
               FD_SET(fd2, &
      
        fdset);


      
      
        372
      
               tv.tv_sec = lfd_host->ka_interval;                            
      
        //
      
      
        非阻塞超時(shí)時(shí)間
      
      
        373
      
               tv.tv_usec = 
      
        0
      
      
        ;


      
      
        374
      
      
        if
      
       ((len = 
      
        select
      
      (maxfd, &fdset, NULL, NULL, &tv)) < 
      
        0
      
      
        )


      
      
        375
      
      
                {


      
      
        376
      
      
                    ....,.


      
      
        377
      
               }                                                             
      
        //
      
      
        select非阻塞監(jiān)控
      
      
        378
      
      
        if
      
       (ka_need_verify)                                           
      
        //
      
      
        ka_need_verify和信號(hào)處理函數(shù)有關(guān)
      
      
        379
      
      
                {


      
      
        380
      
                   ...                                                       
      
        //
      
      
        No input frames, check connection with ECHO,沒輸入信息,發(fā)送請求信息。
      
      
        381
      
      
                }


      
      
        382
      
      
        if
      
       (send_a_packet)                                            
      
        //
      
      
        默認(rèn)為0不加密
      
      
        383
      
      
                {


      
      
        384
      
                   ...                                                       
      
        //
      
      
        加密發(fā)送
      
      
        385
      
      
                }


      
      
        386
      
      
        if
      
       (FD_ISSET(fd1,&fdset) && lfd_check_up())                   
      
        //
      
      
        網(wǎng)絡(luò)套接字fd1是否有數(shù)據(jù)到達(dá),加解密模塊是否準(zhǔn)備就緒。
      
      
        387
      
      
                {


      
      
        388
      
      
                    ....


      
      
        389
      
      
        if
      
       ((len = proto_read(fd1, buf)) <=  
      
        0
      
      )...                
      
        //
      
      
        接收網(wǎng)絡(luò)中數(shù)據(jù)存到buf
      
      
        390
      
                   fl = len & ~VTUN_FSIZE_MASK;                              
      
        //
      
      
        獲取幀標(biāo)志
      
      
        391
      
                   len = len &
      
         VTUN_FSIZE_MASK;


      
      
        392
      
      
        if
      
       (fl)                                                   
      
        //
      
      
         fl即frame flags幀標(biāo)志
      
      
        393
      
      
                    {


      
      
        394
      
                       ...                                                   
      
        //
      
      
        判斷是何種幀,即判斷接收到數(shù)據(jù)的類型請求、應(yīng)答、壞幀、關(guān)閉 。
      
      
        395
      
      
                    }


      
      
        396
      
      
        if
      
       ((len = lfd_run_up(len, buf, &
      
        out
      
      ))  ==  -
      
        1
      
      )...        
      
        //
      
      
        解密
      
      
        397
      
      
        if
      
       (len && dev_write(fd2, 
      
        out
      
      , len) < 
      
        0
      
      
        )


      
      
        398
      
      
                    {


      
      
        399
      
                       ...                                                   
      
        //
      
      
        將網(wǎng)絡(luò)套接字fd1的數(shù)據(jù)寫入虛擬網(wǎng)卡fd2。
      
      
        400
      
      
                    }


      
      
        401
      
      
                }


      
      
        402
      
      
        if
      
       (FD_ISSET(fd2, &fdset) && lfd_check_down())                
      
        //
      
      
        虛擬網(wǎng)卡中是否有數(shù)據(jù),加解密模塊是否就緒。
      
      
        403
      
      
                {


      
      
        404
      
      
        if
      
       ((len = dev_read(fd2, buf, VTUN_FRAME_SIZE)) < 
      
        0
      
      
        )


      
      
        405
      
      
                    {


      
      
        406
      
                       ... 
      
        //
      
      
        讀取虛擬網(wǎng)卡中數(shù)據(jù)
      
      
        407
      
      
                    }


      
      
        408
      
      
        if
      
       ((len = lfd_run_down(len, buf, &
      
        out
      
      ))  ==  -
      
        1
      
      )... 
      
        //
      
      
        加密
      
      
        409
      
      
        if
      
       (len && proto_write(fd1, 
      
        out
      
      , len) < 
      
        0
      
      
        )


      
      
        410
      
      
                    {


      
      
        411
      
                       ... 
      
        //
      
      
        將虛擬網(wǎng)卡fd2中數(shù)據(jù)通過網(wǎng)絡(luò)套接字fd1發(fā)送。
      
      
        412
      
      
                    }


      
      
        413
      
      
                    ...


      
      
        414
      
      
                }


      
      
        415
      
      
                ...


      
      
        416
      
           }
      
        //
      
      
        end while
      
      
        417
      
      
            ...


      
      
        418
      
           proto_write(fd1, buf, VTUN_CONN_CLOSE); 
      
        //
      
      
        通知其他終端本終端連接關(guān)閉
      
      
        419
      
      
            ...


      
      
        420
      
      
        return
      
      
        0
      
      
        ;


      
      
        421
      
      
        }


      
      
        422
      
      
        423
      
      
        424
      
      
        425
      
      
        426
      
      
        /*
      
      
        ********************************************** server端代碼執(zhí)行基本流程分析 ***********************************************
      
      
        */
      
      
        427
      
      
        /*
      
      
        ***************************************************************


      
      
        428
      
      
        *原型:int main(int argc, char* argv[], char* env[]);


      
      
        429
      
      
        *功能:初始化操作,確定是client端還是server端。


      
      
        430
      
      
        *下一步:根據(jù)命令行參數(shù)選擇執(zhí)行client或者server分支,分析server。


      
      
        431
      
      
        ****************************************************************
      
      
        */
      
      
        432
      
      
        int
      
       main(
      
        int
      
       argc, 
      
        char
      
       *argv[], 
      
        char
      
       *
      
        env[])


      
      
        433
      
      
        {


      
      
        434
      
      
            ......


      
      
        435
      
           ......
      
        //
      
      
        初始化vtun結(jié)構(gòu)體。
      
      
        436
      
      
        while
      
       ((opt = getopt(argc, argv, 
      
        "
      
      
        misf:P:L:t:npq
      
      
        "
      
      )) !=  EOF)      
      
        //
      
      
        獲取命令行參數(shù)并進(jìn)行相應(yīng)操作。
      
      
        437
      
      
            {


      
      
        438
      
      
                ......


      
      
        439
      
      
            }


      
      
        440
      
           reread_config(
      
        0
      
      );                                                 
      
        //
      
      
        讀配置文件。
      
      
        441
      
      
            ......


      
      
        442
      
      
            clear_nat_hack_flags(svr);


      
      
        443
      
      
        if
      
       (!svr)                                                         
      
        //
      
      
        如果不是服務(wù)器,再根據(jù)命令行參數(shù)進(jìn)行配置。
      
      
        444
      
      
            {


      
      
        445
      
      
                ......


      
      
        446
      
               hst = argv[optind++];                                         
      
        //
      
      
        vtund server [ip]的第二個(gè)參數(shù)給hst,這個(gè)參數(shù)是服務(wù)器給客戶端定義的名字。
      
      
        447
      
               host = find_host(hst);                                        
      
        //
      
      
        hst是命令行參數(shù),host是配置文件中的對應(yīng)該參數(shù)的會(huì)話信息。
      
      
        448
      
      
                ......


      
      
        449
      
      
            }


      
      
        450
      
           vtun.svr_name = strdup(argv[optind]);                             
      
        //
      
      
        vtund server [ip]的ip給vtun.srv_name
      
      
        451
      
           ......                                                            
      
        //
      
      
        如果vtun結(jié)構(gòu)體的一些成員沒有被初試話,則賦予默認(rèn)值。
      
      
        452
      
      
        switch
      
       (vtun.svr_type)                                            
      
        //
      
      
        判斷vtun的類型,VTUN_STAND_ALONE VTUN_INETD.
      
      
        453
      
      
            {


      
      
        454
      
      
                ......


      
      
        455
      
      
            }


      
      
        456
      
      
        if
      
       (daemon)                                                       
      
        //
      
      
        是否要?jiǎng)?chuàng)建守護(hù)進(jìn)程
      
      
        457
      
      
            {


      
      
        458
      
      
        if
      
       (dofork &&
      
         fork())


      
      
        459
      
      
                 ...


      
      
        460
      
      
            }


      
      
        461
      
      
        if
      
      
         (svr)


      
      
        462
      
      
            {


      
      
        463
      
               memset(&sa, 
      
        0
      
      , 
      
        sizeof
      
      (sa));                                   
      
        //
      
      
        掛起時(shí)讀取配置文件。
      
      
        464
      
               sa.sa_handler =
      
         reread_config;


      
      
        465
      
               sigaction(SIGHUP, &
      
        sa, NULL);


      
      
        466
      
      
        467
      
               init_title(argc, argv, env, 
      
        "
      
      
        vtund[s]: 
      
      
        "
      
      
        );


      
      
        468
      
      
        469
      
      
        if
      
       (vtun.svr_type ==
      
         VTUN_STAND_ALONE)


      
      
        470
      
      
                write_pid();


      
      
        471
      
      
        472
      
               server(sock);                                                 
      
        //
      
      
        執(zhí)行服務(wù)器操作
      
      
        473
      
      
            }


      
      
        474
      
      
        else
      
      
        475
      
      
            {


      
      
        476
      
               init_title(argc, argv, env, 
      
        "
      
      
        vtund[c]: 
      
      
        "
      
      
        );


      
      
        477
      
               client(host);                                                 
      
        //
      
      
        執(zhí)行客戶端操作,host就是從配置文件讀取出的對應(yīng)命令行參數(shù)會(huì)話名的信息。
      
      
        478
      
      
            }


      
      
        479
      
      
            ......


      
      
        480
      
      
        }


      
      
        481
      
      
        482
      
      
        /*
      
      
        ***********************************************************


      
      
        483
      
      
        *原型:void server(int sock);


      
      
        484
      
      
        *參數(shù):sock = 0.


      
      
        485
      
      
        *功能:建立socket以及bind、connect、select等,認(rèn)證暨建立隧道。


      
      
        486
      
      
        *下一步:根據(jù)守護(hù)進(jìn)程類型選擇執(zhí)行l(wèi)istener還是connection。


      
      
        487
      
      
        ************************************************************
      
      
        */
      
      
        488
      
      
        void
      
       server(
      
        int
      
      
         sock)


      
      
        489
      
      
        {


      
      
        490
      
      
        struct
      
       sigaction sa; 
      
        //
      
      
        忽略接收進(jìn)程信號(hào)。
      
      
        491
      
           sa.sa_handler =
      
         SIG_IGN;


      
      
        492
      
           sa.sa_flags =
      
         SA_NOCLDWAIT;


      
      
        493
      
      
            ;


      
      
        494
      
           sigaction(SIGINT, &
      
        sa, NULL);


      
      
        495
      
           sigaction(SIGQUIT, &
      
        sa, NULL);


      
      
        496
      
           sigaction(SIGCHLD, &
      
        sa, NULL);


      
      
        497
      
           sigaction(SIGPIPE, &
      
        sa, NULL);


      
      
        498
      
           sigaction(SIGUSR1, &
      
        sa, NULL);


      
      
        499
      
           vtun_syslog(LOG_INFO, 
      
        "
      
      
        VTUN server ver %s (%s)
      
      
        "
      
      
        , VTUN_VER,


      
      
        500
      
                   vtun.svr_type == VTUN_INETD ? 
      
        "
      
      
        inetd
      
      
        "
      
       : 
      
        "
      
      
        stand
      
      
        "
      
      
        );


      
      
        501
      
      
        switch
      
      
         (vtun.svr_type)


      
      
        502
      
      
        //
      
      
        判斷sever端的類型獨(dú)立啟動(dòng)守護(hù)進(jìn)程or超級(jí)守護(hù)進(jìn)程。
      
      
        503
      
      
            {


      
      
        504
      
      
        case
      
       VTUN_STAND_ALONE: 
      
        //
      
      
        獨(dú)立啟動(dòng)守護(hù)進(jìn)程
      
      
        505
      
               listener(); 
      
        //
      
      
        開始監(jiān)聽
      
      
        506
      
      
        break
      
      
        ;


      
      
        507
      
      
        //
      
      
        超級(jí)守護(hù)進(jìn)程沒有socket、bind、listen、accept過程(inetd實(shí)現(xiàn)該過程),而是直接讀寫開始。
      
      
        508
      
      
        case
      
       VTUN_INETD: 
      
        //
      
      
        守護(hù)進(jìn)程
      
      
        509
      
      
                connection(sock);


      
      
        510
      
      
        break
      
      
        ;


      
      
        511
      
      
            }


      
      
        512
      
      
        }


      
      
        513
      
      
        514
      
      
        /*
      
      
        ***********************************************************


      
      
        515
      
      
        *這里分析獨(dú)立守護(hù)進(jìn)程時(shí)的操作。


      
      
        516
      
      
        *原型:void listener(void);


      
      
        517
      
      
        *功能:建立socket、bind、listen、accept、connection等。


      
      
        518
      
      
        *下一步:connection。


      
      
        519
      
      
        ************************************************************
      
      
        */
      
      
        520
      
      
        void
      
       listener(
      
        void
      
      
        )


      
      
        521
      
      
        {


      
      
        522
      
      
            ...


      
      
        523
      
      
        if
      
       (generic_addr(&my_addr, &vtun.bind_addr) < 
      
        0
      
      ) ...   
      
        //
      
      
        設(shè)置監(jiān)聽地址
      
      
        524
      
      
        if
      
       ((s = socket(AF_INET, SOCK_STREAM, 
      
        0
      
      )) ==  -
      
        1
      
      )... 
      
        //
      
      
        創(chuàng)建socket
      
      
        525
      
           opt = 
      
        1
      
      
        ;


      
      
        526
      
           setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, 
      
        sizeof
      
      
        (opt));


      
      
        527
      
      
        if
      
       (bind(s, (
      
        struct
      
       sockaddr *)&my_addr, 
      
        sizeof
      
      (my_addr)))... 
      
        //
      
      
        bind
      
      
        528
      
      
        if
      
       (listen(s, 
      
        10
      
      
        ))...


      
      
        529
      
           ... 
      
        //
      
      
        信號(hào)處理,防止僵尸進(jìn)程
      
      
        530
      
      
        while
      
       ((!server_term) || (server_term ==
      
         VTUN_SIG_HUP))


      
      
        531
      
      
            {


      
      
        532
      
      
        //
      
      
        注意這個(gè)循環(huán)條件要和linkfd里的循環(huán)條件結(jié)合起來,這里的循環(huán)條件實(shí)際是掛起狀態(tài)才執(zhí)行該循環(huán),


      
      
        533
      
      
        //
      
      
        而不是沒有結(jié)束循環(huán)或者掛起狀態(tài)二者滿足其一執(zhí)行循環(huán)!
      
      
        534
      
      
        if
      
       ((s1 = accept(s,(
      
        struct
      
       sockaddr *)&cl_addr,&opt)) < 
      
        0
      
      ).. 
      
        //
      
      
        accept
      
      
        535
      
      
        switch
      
       (fork()) 
      
        //
      
      
        創(chuàng)建子進(jìn)程
      
      
        536
      
      
                {


      
      
        537
      
      
        case
      
      
        0
      
      
        :


      
      
        538
      
      
                    close(s);


      
      
        539
      
                   connection(s1); 
      
        //
      
      
        和client建立連接,s1是accept返回的已連接套接字描述符(表示此次TCP三次握手連接成功)。
      
      
        540
      
      
        break
      
      
        ;


      
      
        541
      
      
        case
      
       -
      
        1
      
      
        :


      
      
        542
      
                   vtun_syslog(LOG_ERR, 
      
        "
      
      
        Couldn't fork()
      
      
        "
      
      
        );


      
      
        543
      
      
        default
      
      
        :


      
      
        544
      
      
                    close(s1);


      
      
        545
      
      
        break
      
      
        ;


      
      
        546
      
      
                }


      
      
        547
      
      
            }


      
      
        548
      
      
        }


      
      
        549
      
      
        550
      
      
        /*
      
      
        ***********************************************************


      
      
        551
      
      
        *原型:void connection(int sock);


      
      
        552
      
      
        *參數(shù):注意這里的sock是已連接套接字描述符。


      
      
        553
      
      
        *功能:建立socket、bind、listen、accept、connection等。


      
      
        554
      
      
        *下一步:認(rèn)證成功后開啟隧道即執(zhí)行tunnel。


      
      
        555
      
      
        ************************************************************
      
      
        */
      
      
        556
      
      
        void
      
       connection(
      
        int
      
       sock)            
      
        //
      
      
        sock是已連接套接字描述符,和server端監(jiān)聽套接字描述符不同。
      
      
        557
      
      
        {


      
      
        558
      
      
        if
      
       (getpeername(sock, (
      
        struct
      
       sockaddr *) &cl_addr, &opt))...
      
        //
      
      
        獲取client端地址
      
      
        559
      
      
            ...


      
      
        560
      
      
        if
      
       (getsockname(sock, (
      
        struct
      
       sockaddr *) &my_addr, &opt) < 
      
        0
      
      
        )...


      
      
        561
      
      
            ...


      
      
        562
      
      
            io_init();


      
      
        563
      
      
        if
      
       ((host = auth_server(sock)))    
      
        //
      
      
        認(rèn)證
      
      
        564
      
      
            {


      
      
        565
      
            ...        
      
        //
      
      
        忽略掛起信號(hào)
      
      
        566
      
           ...        
      
        //
      
      
        設(shè)置host的一些成員
      
      
        567
      
      
            }


      
      
        568
      
           tunnel(host);                    
      
        //
      
      
        開啟隧道。
      
      
        569
      
      
            ......


      
      
        570
      
      
        }


      
      
        571
      
      
        572
      
      
        /*
      
      
        ***********************************************************************


      
      
        573
      
      
        *補(bǔ)充:在開啟隧道之前先來看看上面函數(shù)涉及的server端認(rèn)證auth_server(sock);


      
      
        574
      
      
        *原型:void connection(int sock);


      
      
        575
      
      
        *參數(shù):注意這里的sock是已連接套接字描述符。


      
      
        576
      
      
        *功能:建立socket、bind、listen、accept、connection等。


      
      
        577
      
      
        ************************************************************************
      
      
        */
      
      
        578
      
      
        struct
      
       vtun_host * auth_server(
      
        int
      
      
         fd)


      
      
        579
      
      
        {


      
      
        580
      
      
            ......


      
      
        581
      
      
        while
      
       (readn_t(fd, buf, VTUN_MESG_SIZE, vtun.timeout) > 
      
        0
      
      ) 
      
        //
      
      
        接收來自客戶端的認(rèn)證信息。
      
      
        582
      
      
            {


      
      
        583
      
      
                ...


      
      
        584
      
      
        switch
      
      
         (stage)


      
      
        585
      
      
                {


      
      
        586
      
      
        case
      
      
         ST_HOST:


      
      
        587
      
      
        if
      
       (!strcmp(str1,
      
        "
      
      
        HOST
      
      
        "
      
      ))                          
      
        //
      
      
        接收來自client的HOST:[host]
      
      
        588
      
      
        589
      
      
                    {


      
      
        590
      
                       host =
      
         strdup(str2);


      
      
        591
      
      
                        gen_chal(chal_req);


      
      
        592
      
                       print_p(fd,
      
        "
      
      
        OK CHAL: %s\n
      
      
        "
      
      , cl2cs(chal_req)); 
      
        //
      
      
        發(fā)送請求發(fā)送秘密信息OK CHAL:[chal]
      
      
        593
      
                       stage =
      
         ST_CHAL;


      
      
        594
      
      
        continue
      
      
        ;


      
      
        595
      
      
                    }


      
      
        596
      
      
        break
      
      
        ;


      
      
        597
      
      
        case
      
      
         ST_CHAL:


      
      
        598
      
      
        if
      
       (!strcmp(str1,
      
        "
      
      
        CHAL
      
      
        "
      
      )) 
      
        //
      
      
        接收密碼
      
      
        599
      
      
        600
      
      
                    {


      
      
        601
      
      
        if
      
       (!
      
        cs2cl(str2, chal_res))


      
      
        602
      
      
        break
      
      
        ;


      
      
        603
      
      
        if
      
       (!(h =
      
         find_host(host)))


      
      
        604
      
      
        break
      
      
        ;


      
      
        605
      
                       decrypt_chal(chal_res, h->
      
        passwd);


      
      
        606
      
      
        if
      
       (!memcmp(chal_req, chal_res, VTUN_CHAL_SIZE)) 
      
        //
      
      
        與配置文件中密碼比較
      
      
        607
      
      
        608
      
      
                        {


      
      
        609
      
      
        /*
      
      
         Auth successeful. 
      
      
        */
      
      
        610
      
      
        /*
      
      
         Lock host 
      
      
        */
      
      
        611
      
      
        if
      
       (lock_host(h) < 
      
        0
      
      
        )


      
      
        612
      
      
                            {


      
      
        613
      
      
        /*
      
      
         Multiple connections are denied 
      
      
        */
      
      
        614
      
                               h =
      
         NULL;


      
      
        615
      
      
        break
      
      
        ;


      
      
        616
      
      
                            }


      
      
        617
      
                           print_p(fd,
      
        "
      
      
        OK FLAGS: %s\n
      
      
        "
      
      , bf2cf(h)); 
      
        //
      
      
        發(fā)送成功信息OK FLAGS:[host]
      
      
        618
      
      
                        }


      
      
        619
      
      
        else
      
      
        620
      
                       h =
      
         NULL;


      
      
        621
      
      
                    }


      
      
        622
      
      
        break
      
      
        ;


      
      
        623
      
               }
      
        //
      
      
        end switch
      
      
        624
      
      
        break
      
      
        ;


      
      
        625
      
           }
      
        //
      
      
        end while
      
      
        626
      
      
            ......


      
      
        627
      
      
        }


      
      
        628
      
      
        629
      
      
        /*
      
      
        ************************************************************************


      
      
        630
      
      
        *原型:int tunnel(strucnt vtun_host* host);


      
      
        631
      
      
        *參數(shù):host是配置文件中某個(gè)會(huì)話所包含的信息


      
      
        632
      
      
        *功能:開啟隧道即初試話設(shè)備讀寫函數(shù),初始化封裝后發(fā)送接收所用協(xié)議。


      
      
        633
      
      
        *下一步:linkfd(host);


      
      
        634
      
      
        *************************************************************************
      
      
        */
      
      
        635
      
      
        int
      
       tunnel(
      
        struct
      
       vtun_host *
      
        host)


      
      
        636
      
      
        {


      
      
        637
      
      
            ......


      
      
        638
      
           ...... 
      
        //
      
      
        接口是否打開
      
      
        639
      
      
        if
      
       (host->
      
        dev)


      
      
        640
      
           {   ...} 
      
        //
      
      
        判斷虛擬設(shè)備類型
      
      
        641
      
      
        if
      
       (!interface_already_open)          
      
        //
      
      
        獲取虛擬設(shè)備文件描述符
      
      
        642
      
      
            {


      
      
        643
      
               ... host->loc_fd = fd[
      
        0
      
      ];         
      
        //
      
      
        虛擬設(shè)備文件描述符存在host->loc_fd中
      
      
        644
      
      
            }


      
      
        645
      
      
        switch
      
       (host->flags & VTUN_PROT_MASK) 
      
        //
      
      
        初始化協(xié)議,tcp還是udp
      
      
        646
      
      
        647
      
      
            {


      
      
        648
      
      
                ......


      
      
        649
      
      
        case
      
      
         VTUN_UDP:


      
      
        650
      
      
        if
      
       ((opt = udp_session(host)) == -
      
        1
      
      
        )


      
      
        651
      
               {   .....} 
      
        //
      
      
        進(jìn)行udp的socket創(chuàng)建等操作
      
      
        652
      
               proto_write =
      
         udp_write;


      
      
        653
      
               proto_read =
      
         udp_read;


      
      
        654
      
      
            }


      
      
        655
      
      
        switch
      
       ((pid =
      
         fork()))


      
      
        656
      
      
            {


      
      
        657
      
      
                ...


      
      
        658
      
      
            }


      
      
        659
      
      
        switch
      
       (host->flags & VTUN_TYPE_MASK) 
      
        //
      
      
        根據(jù)虛擬設(shè)備類型,選擇相應(yīng)虛擬設(shè)備讀寫方式,
      
      
        660
      
      
            {


      
      
        661
      
      
                .....


      
      
        662
      
      
        case
      
      
         VTUN_TUN:


      
      
        663
      
               set_title(
      
        "
      
      
        %s tun %s
      
      
        "
      
      , host->
      
        host, dev);


      
      
        664
      
               dev_read =
      
         tun_read;


      
      
        665
      
               dev_write =
      
         tun_write;


      
      
        666
      
      
        break
      
      
        ;


      
      
        667
      
      
            }


      
      
        668
      
           opt =
      
         linkfd(host);


      
      
        669
      
      
            .......


      
      
        670
      
      
        }


      
      
        671
      
      
        672
      
      
        /*
      
      
        ************************************************************************


      
      
        673
      
      
        *原型:int linkfd(struct vtun_host *host);


      
      
        674
      
      
        *參數(shù):host是配置文件中某個(gè)會(huì)話所包含的信息


      
      
        675
      
      
        *功能:初始化加密解密壓縮解壓模塊。


      
      
        676
      
      
        *下一步:虛擬網(wǎng)卡讀寫以及數(shù)據(jù)的接收發(fā)送lfd_linker();


      
      
        677
      
      
        *************************************************************************
      
      
        */
      
      
        678
      
      
        int
      
       linkfd(
      
        struct
      
       vtun_host *host)        
      
        //
      
      
        鏈接虛擬網(wǎng)卡文件描述符和封裝后用于發(fā)送接收的套接字描述符。
      
      
        679
      
      
        {


      
      
        680
      
      
            ......


      
      
        681
      
           lfd_host =
      
         host;


      
      
        682
      
           old_prio = getpriority(PRIO_PROCESS, 
      
        0
      
      
        );


      
      
        683
      
           setpriority(PRIO_PROCESS, 
      
        0
      
      
        , LINKFD_PRIO);


      
      
        684
      
           ......                                
      
        //
      
      
        Build modules stack加密壓縮等。
      
      
        685
      
           ......                                
      
        //
      
      
        結(jié)束進(jìn)程等信號(hào)處理函數(shù)。
      
      
        686
      
      
            io_init();


      
      
        687
      
           lfd_linker();                         
      
        //
      
      
        虛擬網(wǎng)卡讀寫,封裝解封以及發(fā)送。
      
      
        688
      
           ......                                
      
        //
      
      
        鬧鐘信號(hào)等。
      
      
        689
      
      
        }


      
      
        690
      
      
        691
      
      
        /*
      
      
        ************************************************************************


      
      
        692
      
      
        *原型:int lfd_linker(void)


      
      
        693
      
      
        *功能:虛擬網(wǎng)卡讀寫以及數(shù)據(jù)的接收發(fā)送lfd_linker();


      
      
        694
      
      
        *下一步:結(jié)束。


      
      
        695
      
      
        *************************************************************************
      
      
        */
      
      
        696
      
      
        int
      
       lfd_linker(
      
        void
      
      
        )


      
      
        697
      
      
        {


      
      
        698
      
      
        int
      
       fd1 = lfd_host->rmt_fd; 
      
        //
      
      
        fd1是網(wǎng)絡(luò)套接字描述符,也就是最后封裝發(fā)送的那個(gè)套接字描述符。
      
      
        699
      
      
        int
      
       fd2 = lfd_host->loc_fd; 
      
        //
      
      
        fd2是虛擬網(wǎng)卡設(shè)備文件描述符。
      
      
        700
      
      
            ......


      
      
        701
      
      
        /*
      
      
         Delay sending of first UDP packet over broken NAT routers


      
      
        702
      
      
             because we will probably be disconnected.  Wait for the remote


      
      
        703
      
      
             end to send us something first, and use that connection. 
      
      
        */
      
      
        704
      
      
        if
      
       (!VTUN_USE_NAT_HACK(lfd_host)) 
      
        //
      
      
        ?
      
      
        705
      
      
            proto_write(fd1, buf, VTUN_ECHO_REQ);


      
      
        706
      
      
            ......


      
      
        707
      
      
        while
      
       (!linker_term)
      
        //
      
      
        while循環(huán)體從虛擬網(wǎng)卡讀數(shù)據(jù)后發(fā)送;將接收的數(shù)據(jù)寫入虛擬網(wǎng)卡。
      
      
        708
      
      
            {


      
      
        709
      
      
                ......


      
      
        710
      
               FD_ZERO(&fdset); 
      
        //
      
      
        等待數(shù)據(jù)
      
      
        711
      
               FD_SET(fd1, &
      
        fdset);


      
      
        712
      
               FD_SET(fd2, &
      
        fdset);


      
      
        713
      
               tv.tv_sec = lfd_host->ka_interval; 
      
        //
      
      
        非阻塞超時(shí)時(shí)間
      
      
        714
      
               tv.tv_usec = 
      
        0
      
      
        ;


      
      
        715
      
      
        if
      
       ((len = 
      
        select
      
      (maxfd, &fdset, NULL, NULL, &tv)) < 
      
        0
      
      
        )


      
      
        716
      
               {   ...} 
      
        //
      
      
        select非阻塞監(jiān)控
      
      
        717
      
      
        if
      
       (ka_need_verify) 
      
        //
      
      
        ka_need_verify和信號(hào)處理函數(shù)有關(guān)
      
      
        718
      
      
                {


      
      
        719
      
                   ...
      
        //
      
      
        No input frames, check connection with ECHO,沒輸入信息,發(fā)送請求信息。
      
      
        720
      
      
                }


      
      
        721
      
      
        if
      
       (send_a_packet) 
      
        //
      
      
        默認(rèn)為0不加密
      
      
        722
      
      
                {


      
      
        723
      
                   ...
      
        //
      
      
        加密發(fā)送
      
      
        724
      
      
                }


      
      
        725
      
      
        if
      
       (FD_ISSET(fd1,&fdset) && lfd_check_up())                    
      
        //
      
      
        網(wǎng)絡(luò)套接字fd1是否有數(shù)據(jù)到達(dá),加解密模塊是否準(zhǔn)備就緒。
      
      
        726
      
      
                {


      
      
        727
      
      
                    ....


      
      
        728
      
      
        if
      
       ((len = proto_read(fd1, buf)) < =  
      
        0
      
      )...                
      
        //
      
      
        接收網(wǎng)絡(luò)中數(shù)據(jù)存到buf
      
      
        729
      
                   fl = len & ~VTUN_FSIZE_MASK; 
      
        //
      
      
        獲取幀標(biāo)志
      
      
        730
      
                   len = len &
      
         VTUN_FSIZE_MASK;


      
      
        731
      
      
        if
      
       (fl) 
      
        //
      
      
         fl即frame flags幀標(biāo)志
      
      
        732
      
      
                    {


      
      
        733
      
                       ...
      
        //
      
      
        判斷是何種幀,即判斷接收到數(shù)據(jù)的類型請求、應(yīng)答、壞幀、關(guān)閉 。
      
      
        734
      
      
                    }


      
      
        735
      
      
        if
      
       ((len = lfd_run_up(len, buf, &
      
        out
      
      ))  ==  -
      
        1
      
      )...        
      
        //
      
      
        解密
      
      
        736
      
      
        if
      
       (len && dev_write(fd2, 
      
        out
      
      , len) < 
      
        0
      
      
        )


      
      
        737
      
      
                    {


      
      
        738
      
                       ...
      
        //
      
      
        將網(wǎng)絡(luò)套接字fd1的數(shù)據(jù)寫入虛擬網(wǎng)卡fd2。
      
      
        739
      
      
                    }


      
      
        740
      
      
                }


      
      
        741
      
      
        if
      
       (FD_ISSET(fd2, &fdset) && lfd_check_down())                 
      
        //
      
      
        虛擬網(wǎng)卡中是否有數(shù)據(jù),加解密模塊是否就緒。
      
      
        742
      
      
                {


      
      
        743
      
      
        if
      
       ((len = dev_read(fd2, buf, VTUN_FRAME_SIZE)) < 
      
        0
      
      
        )


      
      
        744
      
      
                    {


      
      
        745
      
                       ...
      
        //
      
      
        讀取虛擬網(wǎng)卡中數(shù)據(jù)
      
      
        746
      
      
                    }


      
      
        747
      
      
        if
      
       ((len = lfd_run_down(len, buf, &
      
        out
      
      ))  ==  -
      
        1
      
      )...
      
        //
      
      
        加密
      
      
        748
      
      
        if
      
       (len && proto_write(fd1, 
      
        out
      
      , len) < 
      
        0
      
      
        )


      
      
        749
      
      
                    {


      
      
        750
      
                       ...
      
        //
      
      
        將虛擬網(wǎng)卡fd2中數(shù)據(jù)通過網(wǎng)絡(luò)套接字fd1發(fā)送。
      
      
        751
      
      
                    }


      
      
        752
      
      
                    ...


      
      
        753
      
      
                }


      
      
        754
      
      
                ...


      
      
        755
      
           }
      
        //
      
      
        end while
      
      
        756
      
      
            ...


      
      
        757
      
           proto_write(fd1, buf, VTUN_CONN_CLOSE);                            
      
        //
      
      
        通知其他終端本終端連接關(guān)閉
      
      
        758
      
      
            ...


      
      
        759
      
      
        return
      
      
        0
      
      
        ;


      
      
        760
      
       }
    

?

一個(gè)VPN項(xiàng)目(Vtun)源碼分析


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!??!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 县级市| 邯郸市| 延长县| 天水市| 通河县| 天峨县| 偃师市| 六枝特区| 晋宁县| 方正县| 宁陕县| 湖北省| 抚顺县| 昌邑市| 云龙县| 桐柏县| 遂宁市| 定州市| 平武县| 闵行区| 曲阳县| 灵武市| 江阴市| 瑞丽市| 崇信县| 灵武市| 成武县| 漳浦县| 大邑县| 永德县| 临澧县| 日喀则市| 姚安县| 济源市| 威信县| 南汇区| 枞阳县| 漳平市| 湖州市| 黄冈市| 祥云县|