jiayi Rss

linux命令行音乐播放器mocp

Posted by jiayi | Posted in openSUSE | Posted on 08-07-2009

3

好一阵子前装的,因为特别喜欢,特别耐用,安装经历特别曲折,忍不住再做次记录。
第一眼看到mocp的截图就一见钟情,简洁、美丽。。。当然,还有些特性很吸引我:音乐格式通吃,支持更换、自定义皮肤,自定义快捷键,最重要的一点,对中文支持灰常好,甚至比图形播放器支持好~

我是在openSUSE 11.0上装的,因为仓库里的包装上运行crash,所以源码安装,版本为 2.4.4,http://moc.daper.net/
不过……编译时依赖的库比较多,而且放wma有一个bug。。。折腾了将近两天…说下编译安装步骤:
1.首先 ./configure 完后,应该得到如下信息:
        —————————————————————-
        MOC will be compiled with:
        Decoder plugins:    mp3 vorbis flac ffmpeg speex
        OSS:               yes
        ALSA:              yes
        JACK:              yes
        DEBUG:             yes
        RCC:               yes
        Network streams:   yes  
        Resampling:        yes
       推荐把README中提到的依赖库都装上……如果没看到上面加粗的两个 plugin ,看看依赖库和头文件有没有装,尤其是头文件。

2. 如此make && make install可以顺利通过,不过播放wma时会crash。这个bug找了N久……最后侥幸从一个warning中发现问 题。原因是新的 ffmpeg 没有提供 avcodec_decode_audio() 函数,而是用新的 avcodec_decode_audio2() 将其替代,修改后OK(后来发现这个bug已经有人提交了,囧)。
       修改 decoder_plugins/ffmpeg/ffmpeg.c
         将 int data_size; 删掉,在 char avbuf[AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof(int16_t)]; 后添加 int data_size = sizeof(avbuf);
         将 avcodec_decode_audio 换成 avcodec_decode_audio2
   太好了,mocp终于能正常工作了~

3. 不过中文显示很扭曲……修改配置文件轻松搞定。配置文件点此下载
    wow,中文显示比jiayi用的kaffine好N倍~

上两张图吧~

terminal:

控制台:

     mocp 挑bug过程中,尝试了其他一些播放器:
     mplay: http://mplay.sourceforge.net/mplayer  mplayer ncurse前端,用perl写的。有些功能做的很细致,安装简单,不过文档较少,中文显示没搞定,而且没有找到播放playlist的方法……
     mp3blaster: 界面在console下显示的一塌糊涂,直接gg……
     mpgxxx: 没印象了……
     cmus: http://onion.dynserv.net/~timo/index.php?page=Projects/cmus 一堆头文件的包含错误,gg
     mpd: http://mpd.wikia.com/wiki/Music_Player_Daemon_Wiki 装上运行断错误,gg
     mplayer: 除了界面……完美的播放器。。
   
     更多播放器:http://moc.daper.net/links
     更多控制台软件:http://forum.byr.edu.cn/wForum/disparticle.php?boardName=Linux&ID=81362&pos=1
 

Linux发送arp请求与接收arp响应

Posted by jiayi | Posted in UNP | Posted on 28-02-2009

0

Linux 中获得本机网卡MAC地址很简单,ioctl()就OK。可如何获得局域网其他主机的MAC地址呢…链路层广播ARP请求然后接收ARP响应。实现介个功能其实已有现成三方库可用,如libnet。不过想加深对协议的理解和Linux网络编程API的理解,jiayi 还是决定用LinuxPF_PACKET自己实现,改啊改,终于成功~以下是大体思路
1. 为数据报分配空间,创建相应的结构体 req,arp 数据报的帧格式如图
        
2. 创建 PF_PACKET 原始套接字,发送套接字为 reqfd,接收套接字为 recvfd
3. 填写链路层通用结构体 reqsa
3. get_ifi()获取本机网络接口数据,填写要发送的ARP数据报 req 结构体,sendto()发送
4. 循环recvfrom()接收ARP响应,滤掉经由本地接口的其他ARP数据报

发送ARP请求能做的事不仅仅获取MAC地址吧…其他“有意义”的事也可以尝试一下下……下面是代码

C code


/**
* @send_arp.c
* @This software is intended to be used as a example to show how to send and receive arp request with Linux * PF_PACKET interface
* @Author:jiayi,http://www.jiayii.com
**/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/types.h>
#include <asm/types.h>
#include <features.h> /* 需要里面的 glibc 版本号 */
#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
        #include <netpacket/packet.h>
        #include <net/ethernet.h> /* 链路层(L2)协议 */
#else
        #include <asm/types.h>
        #include <linux/if_packet.h>
        #include <linux/if_ether.h> /* 链路层协议 */
#endif
#include <netinet/if_ether.h>

#define INLEN 4
#define MAC_BCAST_ADDR  (uint8_t *) "\xff\xff\xff\xff\xff\xff"

void usage_quit(char *arg0);
int get_ifi(char *dev, char *mac, int macln, struct in_addr *lc_addr, int ipln);
void prmac(u_char *ptr);

int main(int argc, char **argv)
{
        if(argc != 2)
                usage_quit(argv[0]);

        int reqfd, recvfd, salen, n;  
        u_char *mac;
        char recv_buf[120], rep_addr[16];
        struct in_addr lc_addr, req_addr;
        struct sockaddr_ll reqsa, repsa;
        struct arp_pkt {
                struct ether_header eh;
                struct ether_arp ea;
                u_char padding[18];
        } req;
       
        bzero(&reqsa, sizeof(reqsa));
        reqsa.sll_family = PF_PACKET;
        reqsa.sll_ifindex = if_nametoindex("eth0");

        if((reqfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_RARP))) < 0) {
                perror("Socket error");
                exit(1);
        }

        mac = (char *)malloc(ETH_ALEN);
        bzero(&req, sizeof(req));

        if(get_ifi("eth0", mac, ETH_ALEN, &lc_addr, INLEN)) {
                fprintf(stderr, "Error: Get host’s information failed\n");
                exit(0);
        }

        /* 填写以太网头部*/
        memcpy(req.eh.ether_dhost, MAC_BCAST_ADDR, ETH_ALEN);
        memcpy(req.eh.ether_shost, mac, ETH_ALEN);
        req.eh.ether_type = htons(ETHERTYPE_ARP);

        /* 填写arp数据 */
        req.ea.arp_hrd = htons(ARPHRD_ETHER);
        req.ea.arp_pro = htons(ETHERTYPE_IP);
        req.ea.arp_hln = ETH_ALEN;
        req.ea.arp_pln = INLEN;
        req.ea.arp_op = htons(ARPOP_REQUEST);
        memcpy(req.ea.arp_sha, mac, ETH_ALEN);
        memcpy(req.ea.arp_spa, &lc_addr, INLEN);
        inet_aton(argv[1], req.ea.arp_tpa);

        if((n = sendto(reqfd, &req, sizeof(req), 0, (struct sockaddr *)&reqsa, sizeof(reqsa))) <= 0) {
                perror("Sendto error");
                exit(1);
        }
        printf("Broadcast arp request of %s, %d bytes be sent\n\n", argv[1], n);

        recvfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
        bzero(recv_buf, sizeof(recv_buf));
        bzero(&repsa, sizeof(repsa));
        salen = sizeof(struct sockaddr_ll);

        while(1) {
                if((n = recvfrom(recvfd, recv_buf, sizeof(req), 0, (struct sockaddr *)&repsa, &salen)) <= 0) {
                        perror("Recvfrom error");
                        exit(1);
                }

                if( ntohs(*(__be16 *)(recv_buf + 20))==2 && !memcmp(req.ea.arp_tpa, recv_buf + 28, 4) ) {
                        printf("Response from %s, %d bytes received\n", argv[1], n);
                        printf("        Peer IP is: %s\n", inet_ntop(AF_INET, (struct in_addr *)(recv_buf + 28), rep_addr, 1024));
                        prmac( (u_char *)(recv_buf + 22) ); //prmac( (u_char *)(recv_buf + 6) );
                        break;
                }
        }

        free(mac);
}

int get_ifi(char *dev, char * mac, int macln, struct in_addr *lc_addr, int ipln)
{
        int reqfd, n;
        struct ifreq macreq;

        reqfd = socket(AF_INET, SOCK_DGRAM, 0);
        strcpy(macreq.ifr_name, dev);

        /* 获取本地接口MAC地址*/
        if(ioctl(reqfd, SIOCGIFHWADDR, &macreq) != 0)
                return 1;
        memcpy(mac, macreq.ifr_hwaddr.sa_data, macln);

        /* 获取本地接口IP地址*/
        if(ioctl(reqfd, SIOCGIFADDR, &macreq) != 0)
                return 1;
        memcpy(lc_addr, &((struct sockaddr_in *)(&macreq.ifr_addr))->sin_addr, ipln);

        return 0;
}      

void prmac(u_char *ptr)
{
        printf("        Peer MAC is: %02x:%02x:%02x:%02x:%02x:%02x\n",*ptr,*(ptr+1),*(ptr+2),*(ptr+3),*(ptr+4),*(ptr+5));
}

void usage_quit(char *arg0)
{
        fprintf(stderr, "Usage: %s <query_IP>\n", arg0);
        exit(1);
}

此程序需要root权限运行,或者设置suid。
此程序用到的结构体,在/usr/include/linux/if_ether.h  /usr/include/linux/if_arp.h  /usr/include/net/ethernet.h  /usr/include/netinet/if_ether.h 中有相应的声明。
其他参考: man packet《TCP/IP 详解 卷一》第四章
如果想偷偷的实验此程序,tcpdump 能够帮你找到接入局域网的其他主机(额,阴暗心理又暴露了…)。

程序运行如下

另一终端 tcpdump 探嗅

新版Linux qq

Posted by jiayi | Posted in Linux | Posted on 15-11-2008

10

LinuxQQ终于出新版了,前两天短不了上腾讯看,今天终于等到了。

说说新功能吧~首先是文件传输,解决了大问题。屏幕截图也很出现了,总算有点正宗qq的感觉。

不过,额…用qq木有声音,这个ms解决起来不是很难吧…期待下一版能得到相应解决~

signal sigaction

Posted by jiayi | Posted in APUE | Posted on 02-11-2008

4

As eople say, the old signal() had number of problems:1. The disposition for a signal was automatically reset to its defualt each time the signal occured. So we had to reestablish the handler on catching the signal. 2.There is, however, another subtle problem after reestablish the handler: There is a window of time –after the signal has occured,but before the call to signal in the signal handler. If the same signal occured int the window of time, it would cause the default action to occur and the handler would never fetch it. 3.It couldn’t control the blocking stat of signal. And so on

Fortunately, the new signal() implemented by sigaction() has fixed those problems. So the following will take us look into the new signal() (My environment is Linux 2.6.25)

CODE

#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<errno.h>

sigset_t newmask,oldmask,pendmask;

void sig_int(int signo);
int main()
{
    if(signal(SIGINT,sig_int)==SIG_ERR) {
        perror("SIGNAL");
        exit(1);
    }

    sigemptyset(&newmask);
    sigaddset(&newmask,SIGCONT);
    if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0) {
        perror("SIGPROCMASK");
        exit(2);
    }
   
    sleep(10);
    printf("nNo SIGINT be blocked and return to main(). n");     /* 中断系统调用后,没有自动restart it */

    /* Reset signal mask which unblocks SIGINT */
    if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0) {
        perror("SIGPROCMASK");
        exit(3);
    }
    else {
        if(sigismember(&oldmask,SIGCONT))
            printf("Out of the handler, SIGCONT blocked——————————-n");
        else
            printf("Out of the handler, SIGCONT unblocked———————————-n");

        if(sigismember(&oldmask,SIGINT))
            printf("Out of the handler, SIGINT blocked———————————-n");
        else
            printf("Out of the handler, SIGINT unblocked———————————-n");
    }

    printf("Sleeping in main()…n");
    sleep(10);
    exit(0);
}

void sig_int(int signo)
{
    printf("nncaught SIGINTn");

    if(sigprocmask(SIG_BLOCK,NULL,&newmask)<0) {
        perror("SIGPENDING");
        exit(3);
    }

    if(sigismember(&newmask,SIGINT))
        printf("SIGINT blockedn");
    else
        printf("SIGINT unblockedn");

    if(sigismember(&newmask,SIGCONT))
        printf("SIGCONT blockedn");
    else
        printf("SIGCONT unblockedn");

    printf("Sleeping…n");
    sleep(5);
}

jiayi:/home/jiayi/apue # ./queue0
^C                    #SIGINT wasn’t be blocked. It was caught immediately on its occurence

caught SIGINT     # In the signal handler
SIGINT blocked   # SIGINT was automatically blocked by signal() in its own handler,
SIGCONT blocked   # SIGCONT was blocked out of the signal handler manually
Sleeping…            # signal handler sleeping
^C^C^C^C^C        # SIGINT was blocked…

caught SIGINT     # When the last signal handler return, the delivery mask was reset to its previous value. So the blocked SIGINT was delivered to the signal handler again. We send SIGINT 5 times, but signal handler merely caught it once. Because SIGINT isn’t a reliable signal and it can’t be queued.
SIGINT blocked   # Be blocked again…
SIGCONT blocked   # Still be blocked…
Sleeping…            # Sleep in the signal handler

No SIGINT be blocked and return to main().
Out of the handler, SIGCONT unblocked———————————-  # As we set the delivery mask to its old value, SIGCONT wasn’t blocked
Out of the handler, SIGINT unblocked———————————-
Sleeping in main()
^C

caught SIGINT   # Caught SIGINT immediately
SIGINT blocked # Automatically be blocked
SIGCONT unblocked
Sleeping…
^C^C^C^C^C

caught SIGINT
SIGINT blocked
SIGCONT unblocked
Sleeping…

The output above tells us:
1.We needn’t  reestablish the handler on catching the signal.There is no window of time. It’s reliable.
2.SIGXXX automatically be blocked in its own handler
3.The process would block until signal handler absolutely return(ie, there is no blocked signal in the handler)

Now, show a implemention of signal() with sigaction()

CODE

typedef void Sigfunc(int);

Sigfunc *signal(int signo, Sigfunc *func)
{
    struct sigaction    act, oact;

    act.sa_handler = func;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (signo == SIGALRM) {
#ifdef  SA_INTERRUPT
        act.sa_flags |= SA_INTERRUPT;
#endif
    } else {
#ifdef  SA_RESTART
        act.sa_flags |= SA_RESTART;
#endif
    }  
    if (sigaction(signo, &act, &oact) < 0)
        return(SIG_ERR);
    return(oact.sa_handler);
}

If we don’t want the signal which triggered the handler to be automatically blocked, the SA_NODEFER flag should be set as the following code added
        act.sa_flags |= SA_NODEFER

Linux 僵死进程(zombie)

Posted by jiayi | Posted in APUE | Posted on 26-10-2008

3

Linux 中有一种“死不瞑目”的进程,叫僵死进程(zombie)。一句话定义僵死进程:In UNIX System terminology, a process that has terminated, but whose parent has not yet waited for it, is called a zombie. 这些进程可以通过 ps 命令查看:ps -el ,带有 Z 标记的为僵死进程。也可以 ps -ef | grep defunc

一个进程exit()后,内核会将它的exit status 转换为 termination status,并由内核记录。可见这个结束的进程并没有真正的被销毁,虽然它已经不占用任何内存和cpu资源,没有任何可执行代码,也不能被调度,但却残留在进程列表里,一旦这种进程过多,系统性能肯定受其影响。这就需要它的父进程为它“收尸”,来获取已经terminate的子进程的终止状态(通常wait()waitpid() 来完成)。如果父进程在子进程之前退出,子进程会变成僵死进程了么…?不会的,这些子进程会被1号进程init 收留,并由1号进程init为它们”收尸“。

为了更好的说明僵死进程这个东东,我们人为的制造一个。。。 

C code


#include<stdio.h>

#include<stdlib.h>
#include<errno.h>
#include<unistd.h>
#include<sys/stat.h>
#include <sys/wait.h>

int
main(void)
{
    pid_t pid;
    pid_t pid1;
    pid_t wait_pid;

    printf("The parent’s pid is %dn",getpid());
    if ((pid = fork()) < 0)  
    {  
        perror("fork error");
    }  
    else if (pid == 0)  
    {       /* first child */
        if ((pid = fork()) < 0)
            perror("fork error");
        else if (pid > 0)
        {
            printf("First child of the parent is %dn",getpid());
            exit(0);
        }

        sleep(1);
        printf("First child’s child awaked…n");
        printf("pid = %d, parent pid = %dn",getpid(), getppid());
        exit(0);
    }
    else /*The parent process*/
    {
        if((pid1=fork())<0)
            perror("Fork");
        else if(pid1==0)
        {
            printf("Second child of the parent is %dn",getpid());
            exit(0);
        }
    }

    sleep(3);
    printf("parent awaked…n");
    if ((wait_pid=waitpid(pid1, NULL, 0)) == pid1)  // wait for second child
    {
        printf("seconde child has been waited: value of wait_pid is %dn",wait_pid);
    }
    while(1)
        ;

    exit(0);
}

编译运行得到

jiayi:/home/jiayi/apue # ./waitpid
The parent’s pid is 20334
Second child of the parent is 20337
First child of the parent is 20335
First child’s child awaked…
pid = 20336, parent pid = 1
parent awaked…
seconde child has been waited: value of wait_pid is 20337

另一个终端运行 ps -ef 得到最后三行

root     20334  9667 90 21:55 pts/7    00:37:28 ./waitpid
root     20335 20334  0 21:55 pts/7    00:00:00 [waitpid] <defunct>
jiayi  20459 20152  0 22:37 pts/2    00:00:00 ps -ef

一句一句分析程序打印的结果
此程序的进程号为20334;父进程第二个子进程的进程号为20337;父进程第一个子进程的进程号为20335(从这两个进程的打印顺序可以看出,两个进程存在竞争);20335的子进程 20336在睡觉,醒来后发现它的父进程变成了1,这是因为2033520336结束之前已经结束,20336进程被1init收留;父进程在睡觉,醒来后通过waitpid()成功获取第二个子进程20337的终止信息,然后很没素质的作起了无限循环…

至此,父进程在循环,两个子进程以及第一个子进程的子进程都已终止。其中第二个子进程 20337 被收尸,彻底销毁;子进程的子进程被1号init 收尸,也完全销毁;第一个子进程呢…? 看一下 ps 命令的结果,同样一句一句看:
20334号父进程在运行,因为它在作无限循环…;20335号子进程由defunct 标记,说明是一个僵死进程…… 另外两个子进程没有被发现,因为它们已经彻底解脱…

实验还没有结束,这时我们摁下 ctrl + c 将无限循环的父进程 20334 干掉,重新 ps -ef ,那个僵死进程也不见了。。。这是因为父进程 20334 被干掉后,僵死进程被1init ”收尸“,从而彻底解脱。。。

额,弄一个僵死进程出来还挺不容易的。。。

SuSE 安装 永中Office

Posted by jiayi | Posted in Linux | Posted on 25-10-2008

9

永中Office出了2009个人集成版,而且完全免费使用~最主要,它有Linux平台的版本

今天有空,在SuSE下装之。功能 字体感觉比OpenOffice要好,估计在Win下可以取代MS Office了,嘿嘿。。。

SuSE安装步骤:
1.在http://www.evermoresw.com.cn/webch/download/downEIOPersonal.jsp下载Linux版本

2,解压包

CODE

tar zxvf EIOffice_Personal_Lin.tar.gz

3.安装
这里说一下,开始直接运行setup.sh文件,弹出的安装对话框一片空白。之前安装其他版本的永中Office也是这种情况。不过SuSE用户别灰心,JAVA运行边可以搞定

CODE

java -jar dispose.jar

一路下一步,OK

4.小小的配置
jiayi的机器运行永中Office,弹出的界面依然空白……想是不是GTK库不兼容…Baidu找到症结,编辑/usr/bin/eio

CODE

vi/usr/bin/eio

看到开头几句,有点崩溃。。。

#!/bin/bash
if test -n "$(grep  "Ubuntu"  /proc/version)"; then
   export AWT_TOOLKIT=MToolkit
else
   export AWT_TOOLKIT=XToolkit
fi

竟然只顾及 Ubuntu 。。。囧…
将上面 #!/bin/bash 后面的语句替换成 export AWT_TOOLKIT=MToolkit,重新启动永中Office。Gooood,It works well~

永中Office做得很符合中国人习惯:MS office 流,字体 界面很舒服。虽然SuSE下的安装有点小波折,不过赞誉是应该的~上张图吧

Unix time functions

Posted by jiayi | Posted in APUE | Posted on 18-10-2008

3



Ext3 file system

Posted by jiayi | Posted in APUE | Posted on 17-10-2008

4

File system

Super
Block
Group
Descriptors
Block
Group 1
Block
Group 2

Block
Group N

Block
Bitmap
Inode
Bitmap
Inode
Table
Data
Blocks

From the figuires above we get:

Every block group is associated with a group descriptor. All of the group descriptors are congregated following the Super Block tightly.

In the group descriptor,there is a pointer points to the refered block group’s block bitmap.Every bit in the block bitmap indicates a block.0 represents the block has been written;1 represents the block is free.The size of block bitmap is just the same as a block.So if  we assume a block is S bytes.The block bitmap can record S*8 blocks.We get that a block group is 8*S*S bytes at most.

There is another pointer in the group descriptor pointing to the inode bitmap.This inode bitmap owns the same size of a block too.Every bit in it refers to a i-node.The i-node laying on the hard disk refers to the file on the file system.The file types are as the follow:

File type

   

regular file

 

 

directory

   

symbolic link

   

character special

   

block special

   

socket

   

FIFO

   

Another important pointer in descriptor points to the I-node table.The I-node table is larger than a block.It gathers all the i-nodes in the block group.

The structure of Supper Block

struct ext3_super_block {
/*00*/ __u32 s_inodes_count;      /* inodes count */
       __u32 s_blocks_count;      /* blocks count */
       __u32 s_r_blocks_count;    /* reserve blocks count */
       __u32 s_free_blocks_count; /* free blocks count */
/*10*/ __u32 s_free_inodes_count; /* free inodes count */
       __u32 s_first_data_block;  /* firest data block */
       __u32 s_log_block_size;    /* size of a block */
       __s32 s_log_frag_size;     /* Ignore */
/*20*/ __u32 s_blocks_per_group;  /* number of blocks per block group */
       __u32 s_frags_per_group;   /* Ignore */
       __u32 s_inodes_per_group;  /* number of inodes per block group */
       __u32 s_mtime;             /* Mount time */
/*30*/ __u32 s_wtime;             /* Write time */
       __u16 s_mnt_count;         /* Mount count */
       __s16 s_max_mnt_count;     /* Maximal mount count */
       __u16 s_magic;             /* Magic label */
       __u16 s_state;             /* File system state */
       __u16 s_errors;            /* Behaviour when detecting errors */
       __u16 s_minor_rev_level;   /* minor revision level */
/*40*/ __u32 s_lastcheck;         /* time of last check */
       __u32 s_checkinterval;     /* max. time between checks */
       __u32 s_creator_os;        /* Ignore */
       __u32 s_rev_level;         /* Revision level */
/*50*/ __u16 s_def_resuid;        /* Default uid for reserved blocks */
       __u16 s_def_resgid;        /* Default gid for reserved blocks */
       __u32 s_first_ino;         /* First non-reserved inode */
       __u16 s_inode_size;        /* size of inode structure */
       __u16 s_block_group_nr;    /* block group # of this superblock */
       __u32 s_feature_compat;    /* compatible feature set */
/*60*/ __u32 s_feature_incompat;  /* incompatible feature set */
       __u32 s_feature_ro_compat; /* readonly-compatible feature set */
/*68*/ __u8  s_uuid[16];          /* 128-bit uuid for volume */
/*78*/ char  s_volume_name[16];   /* volume name */
/*88*/ char  s_last_mounted[64];  /* directory where last mounted */
/*C8*/ __u32 s_algorithm_usage_bitmap; /* Ignore */
       __u8  s_prealloc_blocks;        /* Ignore */
       __u8  s_prealloc_dir_blocks;    /* Ignore */
       __u16 s_padding1;               /* Ignore */
/*D0*/ __u8  s_journal_uuid[16]; /* uuid of journal superblock */
/*E0*/ __u32 s_journal_inum;     /* log file's inode number */
       __u32 s_journal_dev;      /* log file's device number */
       __u32 s_last_orphan;      /* start of list of inodes to delete */
/*EC*/ __u32 s_reserved[197];    /* Ignore */
};

The structure of group descriptor

struct ext3_group_desc
{
 __u32 bg_block_bitmap;      /* block pointer points to block bitmap */
 __u32 bg_inode_bitmap;      /* block pointer points to inode bitmap */
 __u32 bg_inode_table;       /* block pointer points to inodes table */
 __u16 bg_free_blocks_count; /* free blocks count */
 __u16 bg_free_inodes_count; /* free inodes count */
 __u16 bg_used_dirs_count;   /* number of direcotries */
 __u16 bg_pad;               /* Ignore */
 __u32 bg_reserved[3];       /* Ignore */
};

The structure of I-node

struct ext3_inode {
 __u16 i_mode;    /* File mode */
 __u16 i_uid;     /* Low 16 bits of Owner Uid */
 __u32 i_size;    /* size of file,byte unit */
 __u32 i_atime;   /* Access time */
 __u32 i_ctime;   /* Creation time */
 __u32 i_mtime;   /* Modification time */
 __u32 i_dtime;   /* Deletion Time */
 __u16 i_gid;     /* Low 16 bits of Group Id */
 __u16 i_links_count;          /* Links count */
 __u32 i_blocks;               /* blocks count */
 __u32 i_flags;                /* File flags */
 __u32 l_i_reserved1;          /* Ignore */
 __u32 i_block[EXT3_N_BLOCKS]; /* array of block pointers */
 __u32 i_generation;           /* Ignore */
 __u32 i_file_acl;             /* Ignore */
 __u32 i_dir_acl;              /* Ignore */
 __u32 i_faddr;                /* Ignore */
 __u8  l_i_frag;               /* Ignore */
 __u8  l_i_fsize;              /* Ignore */
 __u16 i_pad1;                 /* Ignore */
 __u16 l_i_uid_high;           /* Ignore */
 __u16 l_i_gid_high;           /* Ignore */
 __u32 l_i_reserved2;          /* Ignore */
};


I-node points to directory blocks

From the figuire above we get:

The structure of directory are allocated out of the i-node array (i-node table). It is allocated in the data blocks with the ordinary data together.
Ordinary file i-node points to the ordinary data block. Direcotery i-node points to the direcotery blocks.

Directory block points to the associated i-node


From the figuire above we get:

Directories are structured in a hierarchical tree. Each directory can contain files and subdirectories.
Directories are implemented as a special type of files. Actually, a directory is a file containing a list of entries. Each entry contains an inode number and a file name. When a process uses a pathname, the kernel code searchs in the directories to find the corresponding inode number. After the name has been converted to an inode number, the inode is loaded into memory and is used by subsequent requests.

Linux VPN

Posted by jiayi | Posted in Linux | Posted on 16-10-2008

0

系统环境:CentOS5操作系统。主机VPNSRV01是我的VPN Server。主机VPNCLNT00是我的测试VPN Client。
 
Yum 安装 OpenVPN
=========================================================
[root@VPNSRV01]# yum install openvpn*
Dependencies Resolved
=============================================================================
 Package                 Arch       Version          Repository        Size
=============================================================================
Installing:
 openvpn    (主程序包)              i386       2.0.9-1.el4.rf   dag               345 k
Installing for dependencies:
 lzo2         (相关依赖包)          i386       2.02-3.el4.rf    dag               101 k
 openssl097a   (相关依赖包)         i386       0.9.7a-9         base              825 k
Transaction Summary
=============================================================================
Install      3 Package(s)        
Update       0 Package(s)        
Remove       0 Package(s)        
Total download size: 1.2 M
Is this ok [y/N]: y
Downloading Packages:
(1/3): openvpn-2.0.9-1.el 100% |=========================| 345 kB    00:06    
(2/3): openssl097a-0.9.7a 100% |=========================| 825 kB    00:00    
(3/3): lzo2-2.02-3.el4.rf 100% |=========================| 101 kB    00:03    
warning: rpmts_HdrFromFdno: Header V3 DSA signature: NOKEY, key ID e8562897
Importing GPG key 0xE8562897 "CentOS-5 Key (CentOS 5 Official Signing Key)
<centos-5-key@centos.org>" from ftp://123.123.123.214//RPM-GPG-KEY-CentOS-5
Is this ok [y/N]: y
Running Transaction Test
warning: openvpn-2.0.9-1.el4.rf: Header V3 DSA signature: NOKEY, key ID
6b8d79e6
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing: lzo2                         ######################### [1/3]
  Installing: openssl097a                  ######################### [2/3]
  Installing: openvpn                      ######################### [3/3]
Installed: openvpn.i386 0:2.0.9-1.el4.rf
Dependency Installed: lzo2.i386 0:2.02-3.el4.rf openssl097a.i386 0:0.9.7a-9
Complete!
 
 
 
安装PAM功能包
===============================================================
[root@VPNSRV01]# yum install pam*
Dependencies Resolved
=============================================================================
 Package                 Arch       Version          Repository        Size
=============================================================================
Installing:
 pam-devel               i386       0.99.6.2-3.14.el5  base              186 k
 pam_abl                 i386       0.2.3-1.el4.rf   dag                50 k
 pam_script              i386       0.1.7-1.el4.rf   dag                11 k
 pam_shield              i386       0.9.2-1.el4.rf   dag                39 k
 pam_ssh                 i386       1.91-1.el4.rf    dag                88 k
 pamtester               i386       0.1.2-1.el4.rf   dag                15 k
Installing for dependencies:
 compat-db               i386       4.2.52-5.1       base              1.7 M
Transaction Summary
=============================================================================
Install      7 Package(s)        
Update       0 Package(s)        
Remove       0 Package(s)        
Total download size: 2.1 M
Is this ok [y/N]: y
Downloading Packages:
(1/7): pam_script-0.1.7-1 100% |=========================|  11 kB    00:00    
(2/7): pam_shield-0.9.2-1 100% |=========================|  39 kB    00:01    
(3/7): pam_abl-0.2.3-1.el 100% |=========================|  50 kB    00:01    
(4/7): pam-devel-0.99.6.2 100% |=========================| 186 kB    00:00    
(5/7): pamtester-0.1.2-1. 100% |=========================|  15 kB    00:00    
(6/7): compat-db-4.2.52-5 100% |=========================| 1.7 MB    00:00    
(7/7): pam_ssh-1.91-1.el4 100% |=========================|  88 kB    00:02    
Running Transaction Test
warning: pam_script-0.1.7-1.el4.rf: Header V3 DSA signature: NOKEY, key ID
6b8d79e6
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing: compat-db                    ######################### [1/7]
  Installing: pam_script                   ######################### [2/7]
  Installing: pam_shield                   ######################### [3/7]
  Installing: pam_abl                      ######################### [4/7]
  Installing: pam-devel                    ######################### [5/7]
  Installing: pamtester                    ######################### [6/7]
  Installing: pam_ssh                      ######################### [7/7]
Installed: pam-devel.i386 0:0.99.6.2-3.14.el5 pam_abl.i386 0:0.2.3-1.el4.rf
pam_script.i386 0:0.1.7-1.el4.rf pam_shield.i386 0:0.9.2-1.el4.rf pam_ssh.i386
0:1.91-1.el4.rf pamtester.i386 0:0.1.2-1.el4.rf
Dependency Installed: compat-db.i386 0:4.2.52-5.1
Complete!
 
 
察看OpenVPN的所有相关文档
============================================================
[root@VPNSRV01]# updatedb
[root@VPNSRV01]# locate openvpn
/etc/openvpn
/etc/rc.d/init.d/openvpn
/etc/rc.d/rc0.d/K76openvpn
/etc/rc.d/rc1.d/K76openvpn
/etc/rc.d/rc2.d/K76openvpn
/etc/rc.d/rc3.d/S24openvpn
/etc/rc.d/rc4.d/S24openvpn
/etc/rc.d/rc5.d/S24openvpn
/etc/rc.d/rc6.d/K76openvpn
/usr/sbin/openvpn
/usr/share/openvpn
/usr/share/doc/openvpn-2.0.9
/usr/share/doc/openvpn-2.0.9/AUTHORS
/usr/share/doc/openvpn-2.0.9/COPYING
/usr/share/doc/openvpn-2.0.9/COPYRIGHT.GPL
/usr/share/doc/openvpn-2.0.9/ChangeLog
/usr/share/doc/openvpn-2.0.9/INSTALL
/usr/share/doc/openvpn-2.0.9/NEWS
/usr/share/doc/openvpn-2.0.9/PORTS
/usr/share/doc/openvpn-2.0.9/README
/usr/share/doc/openvpn-2.0.9/README.auth-pam
/usr/share/doc/openvpn-2.0.9/README.down-root
/usr/share/doc/openvpn-2.0.9/README.plugins
/usr/share/doc/openvpn-2.0.9/contrib
/usr/share/doc/openvpn-2.0.9/easy-rsa
/usr/share/doc/openvpn-2.0.9/management
/usr/share/doc/openvpn-2.0.9/sample-config-files
/usr/share/doc/openvpn-2.0.9/sample-keys
/usr/share/doc/openvpn-2.0.9/sample-scripts
/usr/share/doc/openvpn-2.0.9/contrib/README
/usr/share/doc/openvpn-2.0.9/contrib/multilevel-init.patch
/usr/share/doc/openvpn-2.0.9/contrib/openvpn-fwmarkroute-1.00
/usr/share/doc/openvpn-2.0.9/contrib/pull-resolv-conf
/usr/share/doc/openvpn-2.0.9/contrib/openvpn-fwmarkroute-1.00/README
/usr/share/doc/openvpn-2.0.9/contrib/openvpn-fwmarkroute-1.00/fwmarkroute.down
/usr/share/doc/openvpn-2.0.9/contrib/openvpn-fwmarkroute-1.00/fwmarkroute.up
/usr/share/doc/openvpn-2.0.9/contrib/pull-resolv-conf/client.down
/usr/share/doc/openvpn-2.0.9/contrib/pull-resolv-conf/client.up
/usr/share/doc/openvpn-2.0.9/easy-rsa/.externals
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0
/usr/share/doc/openvpn-2.0.9/easy-rsa/README
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows
/usr/share/doc/openvpn-2.0.9/easy-rsa/build-ca
/usr/share/doc/openvpn-2.0.9/easy-rsa/build-dh
/usr/share/doc/openvpn-2.0.9/easy-rsa/build-inter
/usr/share/doc/openvpn-2.0.9/easy-rsa/build-key
/usr/share/doc/openvpn-2.0.9/easy-rsa/build-key-pass
/usr/share/doc/openvpn-2.0.9/easy-rsa/build-key-pkcs12
/usr/share/doc/openvpn-2.0.9/easy-rsa/build-key-server
/usr/share/doc/openvpn-2.0.9/easy-rsa/build-req
/usr/share/doc/openvpn-2.0.9/easy-rsa/build-req-pass
/usr/share/doc/openvpn-2.0.9/easy-rsa/clean-all
/usr/share/doc/openvpn-2.0.9/easy-rsa/list-crl
/usr/share/doc/openvpn-2.0.9/easy-rsa/make-crl
/usr/share/doc/openvpn-2.0.9/easy-rsa/openssl.cnf
/usr/share/doc/openvpn-2.0.9/easy-rsa/revoke-crt
/usr/share/doc/openvpn-2.0.9/easy-rsa/revoke-full
/usr/share/doc/openvpn-2.0.9/easy-rsa/sign-req
/usr/share/doc/openvpn-2.0.9/easy-rsa/vars
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/Makefile
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/README
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/build-ca
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/build-dh
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/build-inter
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/build-key
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/build-key-pass
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/build-key-pkcs12
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/build-key-server
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/build-req
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/build-req-pass
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/clean-all
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/inherit-inter
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/list-crl
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/openssl-0.9.6.cnf
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/openssl.cnf
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/pkitool
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/revoke-full
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/sign-req
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/vars
/usr/share/doc/openvpn-2.0.9/easy-rsa/2.0/whichopensslcnf
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/README.txt
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/build-ca.bat
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/build-dh.bat
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/build-key-pkcs12.bat
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/build-key-server.bat
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/build-key.bat
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/clean-all.bat
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/index.txt.start
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/init-config.bat
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/revoke-full.bat
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/serial.start
/usr/share/doc/openvpn-2.0.9/easy-rsa/Windows/vars.bat.sample
/usr/share/doc/openvpn-2.0.9/management/management-notes.txt
/usr/share/doc/openvpn-2.0.9/sample-config-files/README
/usr/share/doc/openvpn-2.0.9/sample-config-files/client.conf
/usr/share/doc/openvpn-2.0.9/sample-config-files/firewall.sh
/usr/share/doc/openvpn-2.0.9/sample-config-files/home.up
/usr/share/doc/openvpn-2.0.9/sample-config-files/loopback-client
/usr/share/doc/openvpn-2.0.9/sample-config-files/loopback-server
/usr/share/doc/openvpn-2.0.9/sample-config-files/office.up
/usr/share/doc/openvpn-2.0.9/sample-config-files/openvpn-shutdown.sh
/usr/share/doc/openvpn-2.0.9/sample-config-files/openvpn-startup.sh
/usr/share/doc/openvpn-2.0.9/sample-config-files/server.conf
/usr/share/doc/openvpn-2.0.9/sample-config-files/static-home.conf
/usr/share/doc/openvpn-2.0.9/sample-config-files/static-office.conf
/usr/share/doc/openvpn-2.0.9/sample-config-files/tls-home.conf
/usr/share/doc/openvpn-2.0.9/sample-config-files/tls-office.conf
/usr/share/doc/openvpn-2.0.9/sample-config-files/xinetd-client-config
/usr/share/doc/openvpn-2.0.9/sample-config-files/xinetd-server-config
/usr/share/doc/openvpn-2.0.9/sample-keys/README
/usr/share/doc/openvpn-2.0.9/sample-keys/client.crt
/usr/share/doc/openvpn-2.0.9/sample-keys/client.key
/usr/share/doc/openvpn-2.0.9/sample-keys/dh1024.pem
/usr/share/doc/openvpn-2.0.9/sample-keys/pass.crt
/usr/share/doc/openvpn-2.0.9/sample-keys/pass.key
/usr/share/doc/openvpn-2.0.9/sample-keys/pkcs12.p12
/usr/share/doc/openvpn-2.0.9/sample-keys/server.crt
/usr/share/doc/openvpn-2.0.9/sample-keys/server.key
/usr/share/doc/openvpn-2.0.9/sample-keys/tmp-ca.crt
/usr/share/doc/openvpn-2.0.9/sample-keys/tmp-ca.key
/usr/share/doc/openvpn-2.0.9/sample-scripts/auth-pam.pl
/usr/share/doc/openvpn-2.0.9/sample-scripts/bridge-start
/usr/share/doc/openvpn-2.0.9/sample-scripts/bridge-stop
/usr/share/doc/openvpn-2.0.9/sample-scripts/openvpn.init
/usr/share/doc/openvpn-2.0.9/sample-scripts/verify-cn
/usr/share/doc/selinux-policy-2.4.6/html/services_openvpn.html
/usr/share/logwatch/default.conf/services/openvpn.conf
/usr/share/logwatch/scripts/services/openvpn
/usr/share/man/man8/openvpn.8.gz
/usr/share/openvpn/plugin
/usr/share/openvpn/plugin/lib
/usr/share/openvpn/plugin/lib/openvpn-auth-pam.so
/usr/share/openvpn/plugin/lib/openvpn-down-root.so
 
 
将模版中的easy-rsa的目录复制到/etc/openvpn/的路径下
默认安装好OpenVPN的主配置路径/etc/openvpn/下是空的。
[root@VPNSRV01]# cp -r /usr/share/doc/openvpn-2.0.9/easy-rsa/ /etc/openvpn/
察看/etc/openvpn/easy-rsa/下的文件
[root@VPNSRV01]# ll /etc/openvpn/easy-rsa/
total 88
drwxr-xr-x 2 root root 4096 Aug 27 10:20 2.0
-rw-r–r– 1 root root  242 Aug 27 10:20 build-ca
-rw-r–r– 1 root root  228 Aug 27 10:20 build-dh
-rw-r–r– 1 root root  529 Aug 27 10:20 build-inter
-rw-r–r– 1 root root  516 Aug 27 10:20 build-key
-rw-r–r– 1 root root  424 Aug 27 10:20 build-key-pass
-rw-r–r– 1 root root  695 Aug 27 10:20 build-key-pkcs12
-rw-r–r– 1 root root  662 Aug 27 10:20 build-key-server
-rw-r–r– 1 root root  466 Aug 27 10:20 build-req
-rw-r–r– 1 root root  402 Aug 27 10:20 build-req-pass
-rw-r–r– 1 root root  280 Aug 27 10:20 clean-all
-rw-r–r– 1 root root  264 Aug 27 10:20 list-crl
-rw-r–r– 1 root root  268 Aug 27 10:20 make-crl
-rw-r–r– 1 root root 7487 Aug 27 10:20 openssl.cnf
-rw-r–r– 1 root root 6075 Aug 27 10:20 README
-rw-r–r– 1 root root  268 Aug 27 10:20 revoke-crt
-rw-r–r– 1 root root  593 Aug 27 10:20 revoke-full
-rw-r–r– 1 root root  411 Aug 27 10:20 sign-req
-rw-r–r– 1 root root 1266 Aug 27 10:20 vars
drwxr-xr-x 2 root root 4096 Aug 27 10:20 Windows
这里有很多的是脚本文件,但是目前都是没有任何级别的执行权限,因此要用命令给与他们执行的权限
 
创造唯用户添加执行权限的命令ux
[root@VPNSRV01]# alias ux=’chmod u+x’
出于便利和安全性的考虑,并且将这个ux命令赋给root,使root今后一直具有这个命令
[root@VPNSRV01]# echo "alias ux=’chmod u+x’" >> /root/.bashrc
 
察看root的.bashrc文件,进行确认
[root@VPNSRV01]# cat /root/.bashrc
———————————————
# .bashrc
# User specific aliases and functions
alias rm=’rm -i’
alias cp=’cp -i’
alias mv=’mv -i’
# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi
alias ux=’chmod u+x’  (刚才添加进来的)
———————————————–
 
赋予vars脚本用户执行权
[root@VPNSRV01 easy-rsa]# ux vars
使用环境载入方式将vars载入系统环境之中。这里和简单的脚本运行不同,由于vars这个脚本里面定义了许多关键的变量和环境所以简单使用“./”运行是失败的,而必须使用载入的方法“. vars”(点 空格 vars)。
[root@VPNSRV01 easy-rsa]# . vars
NOTE: when you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/easy-rsa/keys
载 入vars脚本后出现提示信息,提示下一步可以运行clean-all的脚本了。并且一旦运行这个文件就会清空/etc/openvpn/easy- rsa/keys/下的所有文件了。这里有2个问题:1.它怎么知道我的路径是/etc/openvpn呢?如果我换了的话,它提示出来的还是这个路径 么?答
案就在vars这个环境脚本当中,它是使用pwd来定义我们设置的openvpn配置文档路径的,这就能动态地捕获我们运行vars的任何 路径,也就是说我们现在正在忙着操作的当前路径,都是通过载入vars时的pwd来动态定义的。2.提示中提到的keys这个目录好像没有看到?对的,现 在是没有,接下来根据提示运行clean-all的时候就可以得到答案。另外需要注意的一点,这里通过执行脚本的方式载入变量和环境,而不是永久载入,重 启机器后就会丢失这些环境。建议考虑通过一些方法将vars内的环境永久载入系统,比如可以考虑将执行脚本的命令加入系统启动脚本当中。
 
赋予clean-all脚本的用户执行权限
[root@VPNSRV01 easy-rsa]# ux clean-all
执行clean-all脚本
[root@VPNSRV01 easy-rsa]# ./clean-all
察看现在/etc/openvpn/easy-rsa/下的文件
[root@VPNSRV01 easy-rsa]# ll /etc/openvpn/easy-rsa/
total 92
drwxr-xr-x 2 root root 4096 Aug 27 10:20 2.0
-rw-r–r– 1 root root  242 Aug 27 10:20 build-ca
-rw-r–r– 1 root root  228 Aug 27 10:20 build-dh
-rw-r–r– 1 root root  529 Aug 27 10:20 build-inter
-rw-r–r– 1 root root  516 Aug 27 10:20 build-key
-rw-r–r– 1 root root  424 Aug 27 10:20 build-key-pass
-rw-r–r– 1 root root  695 Aug 27 10:20 build-key-pkcs12
-rw-r–r– 1 root root  662 Aug 27 10:20 build-key-server
-rw-r–r– 1 root root  466 Aug 27 10:20 build-req
-rw-r–r– 1 root root  402 Aug 27 10:20 build-req-pass
-rwxr–r– 1 root root  280 Aug 27 10:20 clean-all
drwx—— 2 root root 4096 Aug 27 10:41 keys (多出来了这个keys目录)
-rw-r–r– 1 root root  264 Aug 27 10:20 list-crl
-rw-r–r– 1 root root  268 Aug 27 10:20 make-crl
-rw-r–r– 1 root root 7487 Aug 27 10:20 openssl.cnf
-rw-r–r– 1 root root 6075 Aug 27 10:20 README
-rw-r–r– 1 root root  268 Aug 27 10:20 revoke-crt
-rw-r–r– 1 root root  593 Aug 27 10:20 revoke-full
-rw-r–r– 1 root root  411 Aug 27 10:20 sign-req
-rwxr–r– 1 root root 1266 Aug 27 10:20 vars
drwxr-xr-x 2 root root 4096 Aug 27 10:20 Windows
这 里就回答了上面的第二个问题。keys这个目录好像之前没有的?对的,现在是没有,就是要运行接下来的clean-all脚本才会初始化生成的(如果以前 没有的话),如果以前就有这个目录的话(你可以尝试在运行clean-all之前自己mkdir一个keys并且在里面丢些杂七杂八的东西),那么当你运 行clean-all的时候,自动会把keys目录下的所有东西都清空一遍。事实上Keys这个目录就是我们之后生成并存放证书以及密钥的目录。Keys 这个具体生成的路径是由vars环境脚本中KEY_DIR来决定的。
 
建立CA证书
按我的理解来简单介绍下这里OpenVPN的概念证书和密钥的概念。
首 先需要的就是一张根证书和根密钥,根证书CA。OpenVPN的Server端和Client端都会有各自的证书和密钥,不过,一套Server和 Clients都使用同一个CA根证书,这个是他们成为一套的关键大前提,之后生成的Server证书和密钥以及Client的证书和密钥都是根据这个 CA
来签发的,因此会成为一套,因为他们通过CA而互相关联了起来。换句话说,能够成为一套OpenVPN的Server和Client的VPN 系统的话,他们的Server的证书和密钥以及Client的证书和密钥必须由同一个CA证书签发,并且在实际使用和连接的时候需要用同一个CA来验证。
赋予build-ca脚本用户执行权限,build-ca脚本就是生成根证书CA的脚本。
[root@VPNSRV01 easy-rsa]# ux build-ca
执行build-ca脚本
[root@VPNSRV01 easy-rsa]# ./build-ca
———————————————————————————-
Generating a 1024 bit RSA private key
…..++++++
……++++++
writing new private key to ‘ca.key’—–
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, the field will be left blank.
—– (在生成CA证书的过程中会有交互式的提问过程,主要是收集证书的信息)
Country Name (2 letter code) [KG]:CN  (这里提问国家,我填写CN表示中国)
State or Province Name (full name) [NA]:Shanghai   (这里提问省或州名)
Locality Name (eg, city) [BISHKEK]:Shanghai  (这里提问地点)
Organization Name (eg, company) [OpenVPN-TEST]:Center   (这里提问使用者的机构或者集团名称)
Organizational Unit Name (eg, section) []:Center   (这里提问部门单位)
Common Name (eg, your name or your server’s hostname) []:VPNSYS01   (这里提问通用名,注意,一套VPN服务端客户端系统使用同一个CA,共享同一个CA通用名CA Common Name)
Email Address [me@myhost.mydomain]:kanecruiseisgod@hotmail.com   (这里填写管理员的Email信箱)
———————————————————————————-
(注:如果这里发觉自己填错的话,干净回去执行clean-all脚本,清空keys下刚生成的密钥。然后使用build-ca重新做。如果到后面生成服务器和客户端的证书和密钥的时候想要返工就工作量大了。囧)
这个时候可以去keys目录下看看产生的CA根证书和根密钥啦
[root@VPNSRV01 easy-rsa]# ll keys
total 12
-rw-r–r– 1 root root 1233 Aug 27 11:39 ca.crt   (根证书生成)
-rw——- 1 root root  887 Aug 27 11:39 ca.key  (根密钥生成)
-rw-r–r– 1 root root    0 Aug 27 11:34 index.txt
-rw-r–r– 1 root root    3 Aug 27 11:34 serial
 
建立DH参数文件
按照OpenVPN的手册中提到,Diffie-Hellman参数文件(dh-pem文件)的作用是:在一个SSL/TLS连接中,服务端必须要有的。通过build-dh这个脚本来生成dh-pem文件,首先要赋予它用户执行权限
[root@VPNSRV01 easy-rsa]# ux build-dh
执行build-dh脚本,来生成dh文件
[root@VPNSRV01 easy-rsa]# ./build-dh
————————————————————————————–
Generating DH parameters, 1024 bit long safe prime, generator 2This is going to take a long time
……………+……………………………………………….+…………………………………………………………………………..
………………..+….+……+………………………+…………+…………………+…………….+……………………………………+..
…+………..+……………………………………+………..+…………………………+……………………………+………………..
……+………………………+….+…+………………………….+……………………………………………………………………….
……………+…………………………………………….+………………………………………………………………….+…………
………………+………………………………..+.+………………………++*++*++*
(这里它提示说会需要很长时间,但是基本上会很短,因为这里我使用了默认安装长度1024bit)
————————————————————————————–
这个时候可以去keys目录下看看产生的dh-pem文件啦
[root@VPNSRV01 easy-rsa]# ll keys
total 16
-rw-r–r– 1 root root 1233 Aug 27 11:39 ca.crt
-rw——- 1 root root  887 Aug 27 11:39 ca.key
-rw-r–r– 1 root root  245 Aug 27 11:56 dh1024.pem   (dh-pem文件生成)
-rw-r–r– 1 root root    0 Aug 27 11:34 index.txt
-rw-r–r– 1 root root    3 Aug 27 11:34 serial
 
建立OpenVPN Server端的证书和密钥
每台OpenVPN Server都需要生成自己的证书和密钥,当然这都是根据之前的CA根证书签发的,使用build-key-server执行脚本来生成。赋予脚本build-key-servers的用户执行权限
[root@VPNSRV01 easy-rsa]# ux build-key-server
生成Server的证书和密钥。注意,这里执行build-key-server脚本后面要跟参数,参数就是Server证书生成的文件名。
[root@VPNSRV01 easy-rsa]# ./build-key-server vpnsrv01
————————————————————————————
Generating a 1024 bit RSA private key
.++++++………………………………++++++
writing new private key to ‘vpnsrv01.key’—–
You are about to be asked to enter information that will be incorporatedinto your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,If you enter ‘.’, the field will be left blank.—–
Country Name (2 letter code) [KG]:CN   (提问国家)
State or Province Name (full name) [NA]:Shanghai  (提问州或省市名)
Locality Name (eg, city) [BISHKEK]:Shanghai  (提问所在地名)
Organization Name (eg, company) [OpenVPN-TEST]:Center  (提问组织名)
Organizational Unit Name (eg, section) []:Center  (提问组织单位名)
Common Name (eg, your name or your server’s hostname) []:VPNSRV01  (给出Server的名称)
Email Address [me@myhost.mydomain]:kanecruiseisgod@hotmail.com  (给出管理员的信箱地址)
(在Server的证书签发过程中,会有需要提供一些Exatra“额外”的信息)
Please enter the following ‘extra’ attributes to be sent with your certificate request
A challenge password []:123456  (需要提供挑战式握手的密码)
An optional company name []:Center   (提供一个可选的公司名)
Using configuration from /etc/openvpn/easy-rsa/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject’s Distinguished Name is as follows
countryName           :P RINTABLE:’CN’
stateOrProvinceName   :P RINTABLE:’Shanghai’
localityName          :P RINTABLE:’Shanghai’
organizationName      :P RINTABLE:’Center’
organizationalUnitName:PRINTABLE:’Center’
commonName            :P RINTABLE:’VPNSRV01′
emailAddress          :IA5STRING:’kanecruiseisgod@hotmail.com’
Certificate is to be certified until Aug 24 04:43:37 2017 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
(使用CA根证书将这个Server的证书签发了)
————————————————————————————-
(那么这些在Server证书签发过程中提问到的内容有些什么要求吗?答案是有的,我之前做了一张服务器证书就废掉的,理由就是地址信息与CA的不符合,也就是说尽量将一些基本信息与CA证书上回答的基本吻合。)
然后再看下keys下面又多了些什么东西
[root@VPNSRV01 easy-rsa]# ll keys
total 44
-rw-r–r– 1 root root 3636 Aug 27 12:43 01.pem        (多了一个dh-pem文件)
-rw-r–r– 1 root root 1233 Aug 27 11:39 ca.crt
-rw——- 1 root root  887 Aug 27 11:39 ca.key
-rw-r–r– 1 root root  245 Aug 27 11:56 dh1024.pem
-rw-r–r– 1 root root   99 Aug 27 12:43 index.txt
-rw-r–r– 1 root root   21 Aug 27 12:43 index.txt.attr
-rw-r–r– 1 root root    0 Aug 27 11:34 index.txt.old
-rw-r–r– 1 root root    3 Aug 27 12:43 serial
-rw-r–r– 1 root root    3 Aug 27 11:34 serial.old
-rw-r–r– 1 root root 3636 Aug 27 12:43 vpnsrv01.crt  (Server的证书文件)
-rw-r–r– 1 root root  753 Aug 27 12:43 vpnsrv01.csr  (Server的SSL请求请求文件)
-rw——- 1 root root  887 Aug 27 12:43 vpnsrv01.key  (Server的密钥文件)
 
建立OpenVPN Client端的证书和密钥
每台OpenVPN Client都要有自己的证书和密钥,当然这些也是根据之前的CA证书来签发的,使用build-key执行脚本来生成
赋予脚本build-key用户执行权限
[root@VPNSRV01 easy-rsa]# ux build-key
生成Client的证书和密钥。注意,这里执行build-key脚本后面要跟参数,参数就是Client证书生成的文件名。
[root@VPNSRV01 easy-rsa]# ./build-key vpnclnt00  (编号00表示测试用,我的习惯)
————————————————————————————-
Generating a 1024 bit RSA private key
……++++++…………..++++++
writing new private key to ‘vpnclnt00.key’—–
You are about to be asked to enter information that will be incorporated into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, the field will be left blank.
—–
Country Name (2 letter code) [KG]:CN  (提问国家)
State or Province Name (full name) [NA]:Shanghai  (提问州或省市名)
Locality Name (eg, city) [BISHKEK]:Shanghai  (提问所在地名)
Organization Name (eg, company) [OpenVPN-TEST]:Center  (提问组织名)
Organizational Unit Name (eg, section) []:Center  (提问组织单位名)
Common Name (eg, your name or your server’s hostname) []:VPNCLNT00  (给出Client的名称)
Email Address [me@myhost.mydomain]:kanecruiseisgod@hotmail.com  (管理员的Email地址)
(在Client的证书签发过程中,也需要提供一些Exatra“额外”的信息)
Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:123456  (挑战式验证口令)
An optional company name []:Center  (一个可选的公司名称)
Using configuration from /etc/openvpn/easy-rsa/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject’s Distinguished Name is as follows
countryName           :P RINTABLE:’CN’
stateOrProvinceName   :P RINTABLE:’Shanghai’
localityName          :P RINTABLE:’Shanghai’
organizationName      :P RINTABLE:’Center’
organizationalUnitName:PRINTABLE:’Center’
commonName            :P RINTABLE:’VPNCLNT00′
emailAddress          :IA5STRING:’kanecruiseisgod@hotmail.com’
Certificate is to be certified until Aug 24 05:00:46 2017 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
(使用CA根证书将这个Client的证书签发了)
————————————————————————————-
(和生成Server的证书一样,Client证书签发过程中使用的基本信息请尽量与CA根证书当中的一致)
然后再看下keys下面又多了些什么东西
[root@VPNSRV01 easy-rsa]# ll keys
total 68
-rw-r–r– 1 root root 3636 Aug 27 12:43 01.pem
-rw-r–r– 1 root root 3537 Aug 27 13:00 02.pem       (又多了一个dh-pem文件)
-rw-r–r– 1 root root 1233 Aug 27 11:39 ca.crt
-rw——- 1 root root  887 Aug 27 11:39 ca.key
-rw-r–r– 1 root root  245 Aug 27 11:56 dh1024.pem
-rw-r–r– 1 root root  199 Aug 27 13:00 index.txt
-rw-r–r– 1 root root   20 Aug 27 13:00 index.txt.attr
-rw-r–r– 1 root root   21 Aug 27 12:43 index.txt.attr.old
-rw-r–r– 1 root root   99 Aug 27 12:43 index.txt.old
-rw-r–r– 1 root root    3 Aug 27 13:00 serial
-rw-r–r– 1 root root    3 Aug 27 12:43 serial.old
-rw-r–r– 1 root root 3537 Aug 27 13:00 vpnclnt00.crt   (Client的证书文件)
-rw-r–r– 1 root root  753 Aug 27 13:00 vpnclnt00.csr   (Client的SSL请求证书文件)
-rw——- 1 root root  887 Aug 27 13:00 vpnclnt00.key   (Client的密钥文件)
-rw-r–r– 1 root root 3636 Aug 27 12:43 vpnsrv01.crt 
-rw-r–r– 1 root root  753 Aug 27 12:43 vpnsrv01.csr
-rw——- 1 root root  887 Aug 27 12:43 vpnsrv01.key
 
为防止恶意攻击(如DOS、UDP port flooding),生成一个"HMAC firewall"
[root@VPNSRV01 easy-rsa]# openvpn –genkey –secret /etc/openvpn/easy-rsa/keys/ta.key
察看keys下生成ta文件
[root@VPNSRV01 easy-rsa]# ll keys
total 72
-rw-r–r– 1 root root 3636 Aug 27 12:43 01.pem
-rw-r–r– 1 root root 3537 Aug 27 13:00 02.pem
-rw-r–r– 1 root root 1233 Aug 27 11:39 ca.crt
-rw——- 1 root root  887 Aug 27 11:39 ca.key
-rw-r–r– 1 root root  245 Aug 27 11:56 dh1024.pem
-rw-r–r– 1 root root  199 Aug 27 13:00 index.txt
-rw-r–r– 1 root root   20 Aug 27 13:00 index.txt.attr
-rw-r–r– 1 root root   21 Aug 27 12:43 index.txt.attr.old
-rw-r–r– 1 root root   99 Aug 27 12:43 index.txt.old
-rw-r–r– 1 root root    3 Aug 27 13:00 serial
-rw-r–r– 1 root root    3 Aug 27 12:43 serial.old
-rw——- 1 root root  636 Aug 27 13:21 ta.key          (ta的密钥文件)
-rw-r–r– 1 root root 3537 Aug 27 13:00 vpnclnt00.crt
-rw-r–r– 1 root root  753 Aug 27 13:00 vpnclnt00.csr
-rw——- 1 root root  887 Aug 27 13:00 vpnclnt00.key
-rw-r–r– 1 root root 3636 Aug 27 12:43 vpnsrv01.crt
-rw-r–r– 1 root root  753 Aug 27 12:43 vpnsrv01.csr
-rw——- 1 root root  887 Aug 27 12:43 vpnsrv01.key
 
生成一个吊销证书链文件
如果证书文件不幸由于各种原因丢失,那么持有丢失证书的人将仍然可以使用进行接入。不用销毁整个系统,可以吊销丢失的证书。执行脚本make-crl先生成吊销证书链文件。
赋予make-crl脚本用户执行权限
[root@VPNSRV01 easy-rsa]# ux make-crl
执行make-crl脚本生成吊销证书链文件
[root@VPNSRV01 easy-rsa]# ./make-crl vpncrl.pem
Using configuration from /etc/openvpn/easy-rsa/openssl.cnf
察看keys下的文件
[root@VPNSRV01 easy-rsa]# ll keys
total 76
-rw-r–r– 1 root root 3636 Aug 27 12:43 01.pem
-rw-r–r– 1 root root 3537 Aug 27 13:00 02.pem
-rw-r–r– 1 root root 1233 Aug 27 11:39 ca.crt
-rw——- 1 root root  887 Aug 27 11:39 ca.key
-rw-r–r– 1 root root  245 Aug 27 11:56 dh1024.pem
-rw-r–r– 1 root root  199 Aug 27 13:00 index.txt
-rw-r–r– 1 root root   20 Aug 27 13:00 index.txt.attr
-rw-r–r– 1 root root   21 Aug 27 12:43 index.txt.attr.old
-rw-r–r– 1 root root   99 Aug 27 12:43 index.txt.old
-rw-r–r– 1 root root    3 Aug 27 13:00 serial
-rw-r–r– 1 root root    3 Aug 27 12:43 serial.old
-rw——- 1 root root  636 Aug 27 13:21 ta.key
-rw-r–r– 1 root root 3537 Aug 27 13:00 vpnclnt00.crt
-rw-r–r– 1 root root  753 Aug 27 13:00 vpnclnt00.csr
-rw——- 1 root root  887 Aug 27 13:00 vpnclnt00.key
-rw-r–r– 1 root root  491 Aug 27 13:28 vpncrl.pem      (证书吊销链文件)
-rw-r–r– 1 root root 3636 Aug 27 12:43 vpnsrv01.crt
-rw-r–r– 1 root root  753 Aug 27 12:43 vpnsrv01.csr
-rw——- 1 root root  887 Aug 27 12:43 vpnsrv01.key

由于MSN空间的字数限制= =
我那华丽的第18集伪系统工程师的故事硬是被划分了上下两集。郁闷…继续上集内容
 
 
整备OpenVPN的Server和Client的主配置文件
之前locate出来的列表当中,有Server和Client的主配置文件模版
/usr/share/doc/openvpn-2.0.9/sample-config-files/client.conf
/usr/share/doc/openvpn-2.0.9/sample-config-files/server.conf
 
OpnVPN Server端的主配置文件
主配置文件的路径为/etc/openvpn/下,因此先将模版配置文件复制到这个路径下再作修改
[root@VPNSRV01 easy-rsa]# cp /usr/share/doc/openvpn-2.0.9/sample-config-files/server.conf /etc/openvpn/
然后配置服务端的主配置文件server.conf
[root@VPNSRV01 openvpn]# vi server.conf
——————————————————————————-
# listen on? (optional)
;local a.b.c.d  (设定监听在本机的哪个网络接口上,这里使用默认注释,表示监听所有本机上的网络接口)
port 9988   (这里设定的监听端口,默认是1194,我这里修改为9988)
  
# TCP or UDP server?
;proto tcp
proto udp
(设定在传输层使用的协议,这里设定为默认的UDP协议)
 
# "dev tun" will create a routed IP tunnel,
# "dev tap" will create an ethernet tunnel.
;dev tap
dev tun
(设定传输设备节点。如提示信息,tun是一个三层设备,tap是一个二层设备。而这里我们要的是IP路由,是三层的方式,因此选择tun)
 
# Non-Windows systems usually don’t need this.
;dev-node MyTap
(设定传输设备节点名。如提示信息,非Windows系统不需要设定这项,目前这台Server的操作系统是CentOS5,保留注释)
 
ca /etc/openvpn/vpnkeys/ca.crt
cert /etc/openvpn/vpnkeys/vpnsrv01.crt
key /etc/openvpn/vpnkeys/vpnsrv01.key  # This file should be kept secret
(设定根证书CA、服务器证书、以及服务器密钥文件的位置。注意,这里我都是写上了绝对路径,那是因为我更动了它们的位置。这里也可以直接写文件名而不写绝对路径,表示使用默认路径,默认为/etc/openvpn/下)
 
dh /etc/openvpn/vpnkeys/dh1024.pem
(设定Diffie Hellman参数文件的路径。同上,我也是输入了绝对路径,也可以直接输入文件名使用默认路径。默认路径为/etc/openvpn/下)
 
# Configure server mode and supply a VPN subnet
server 10.99.0.0 255.255.255.0
(设定Server端虚拟出来的VPN网段)
 
ifconfig-pool-persist ipp.txt
(设定虚拟地址租约文件,用于记录某个Client获得的IP地址,类似于dhcpd.lease文件,防止openvpn重新启动后“忘记”Client曾经使用过的IP地址)
 
push "route 111.111.111.0 255.255.255.0"  #For Net1
push "route 222.222.0.0 255.255.0.0"  #For Net2
push "route 123.123.123.234 255.255.255.255"  #For HostX
(设 定Push路由。当Client连接Server的时候,自动会得到这些路由条目并添加到它们的路由表中,由于是Server那里传过来的,因此叫 Push路由。当Client从Server处断开的时候这些Push路由将自动在Client的路由表中删除。一个需要提醒注意的地方就是既然是加入路 由,那么必须要填写的是"route 网段 子网掩码"的格式,如果不是像第三条那样是添加针对某一个主机的路由的话,那么一定要写的是网段!如果要针对一个目的网段的路由,而却写的是主机地址的 话,那么这个Push路由将失败)
 
;push "redirect-gateway"
;push "dhcp-option DNS 10.8.0.1"
;push "dhcp-option WINS 10.8.0.1"
(设 定其他的Push信息。redirect-gateway为接入Client重新指定出口网关,如果不设定的话则是使用Server路由表当中的默认出口 网关。dhcp-option下的DNS和WIN则是为接入Client重新分配域名服务器和名称服务器的IP地址。除非特殊的规划,一般这里没有设定的 必要,保持注释)
 
client-to-client
(设定接入的Client之间能够被允许互相访问,默认情况下接入的Client是不能互相访问的。如果需要使它们互相访问的话请去掉默认的注释)
 
# IF YOU HAVE NOT GENERATED INDIVIDUAL
# CERTIFICATE/KEY PAIRS FOR EACH CLIENT,
# EACH HAVING ITS OWN UNIQUE "COMMON NAME",
# UNCOMMENT THIS LINE OUT.
;duplicate-cn
(设 定是否允许单证书多连接。如果有多个Client使用相同的证书接入Server,亦或Client使用的CA的Common Name有重复了,或者说客户都使用相同的CA和keys连接VPN,一定要打开这个选项,否则只允许一个人连接VPN。但是如果出于安全考虑,比如一个 证书只能由一个Client对应的情况,这里就建议关闭而保留注释)
 
keepalive 10 120
(设定保活参数。这里的意思是每10秒钟通过Ping来确定Client是否存活,当然这个Ping的进行是在虚拟通道中而不是在真实外部链路上的,超过120秒无反馈表示丢失该Client)
 
# For extra security beyond that provided
# by SSL/TLS, create an "HMAC firewall"
# to help block DoS attacks and UDP port flooding.
#
# Generate with:
#   openvpn –genkey –secret ta.key
#
# The server and each client must have
# a copy of this key.
# The second parameter should be ‘0′
# on the server and ‘1′ on the clients.
tls-auth /etc/openvpn/vpnkeys/ta.key 0 # This file is secret
(设定ta密钥的路径。之前提到的HMAC防火墙,防止DOS攻击,对于所有的控制信息,都使用HMAC signature,没有HMAC signature的控制信息不予处理,注意server端后面的数字肯定使用0,client使用1)
 
# Enable compression on the VPN link.
# If you enable it here, you must also
# enable it in the client config file.
comp-lzo
(使用Lzo功能对虚拟链路进行压缩。另外要提的一点,如果Server端开启的话,那么连接它的Client端也要在配置文件中开启)
 
;max-clients 100
(设定并发最大Client接入数)
 
user nobody
group nobody
(设 定OpenVPN服务的宿主用户,这里设定nobody。使用vipw来快速查看/etc/passwd文件,可以发现nobody是系统内置的,并且 UID和GID分别为99。另外要注意的是,既然将OpenVPN服务的宿主用户设定为nobody,那么凡是关于OpenVPN服务进程相关或者需要读 写的文件,请都要赋予nobody权限)
 
persist-key
(设定连接保持密钥功能。在由于keepalive检测超时后而重新启动VPN的情况,不重新读取keys,而保留第一次使用的keys)
persist-tun
(设定连接保持在线功能。在由于keepalive检测超时后而重新启动VPN的情况,一直保持tun或者tap设备是linkup的,否则网络连接会先linkdown然后linkup)
 
status /var/log/openvpn-status.log
(设定状态记录日志路径。状态记录日志会定期把openvpn的一些状态信息写到文件中,以便自己写程序计费或者进行其他操作。注意,如果更改过OpenVPN服务宿主用户的话,请记得这里将此文件赋予宿主用户一定的权限)
 
log         /var/log/openvpn.log
(设定OpenVPN的服务日志路径。注意,如果更改过OpenVPN服务宿主用户的话,请记得这里将此文件赋予宿主用户一定的权限)
log-append  /var/log/openvpn.log
(此项和log项配合使用,每次重新启动openvpn后保留原有的log信息,新信息追加到文件最后)
 
# 0 is silent, except for fatal errors
# 4 is reasonable for general usage
# 5 and 6 can help to debug connection problems
# 9 is extremely verbose
verb 3
(设定OpenVPN的dubug等级。使用默认3级。)
 
# Silence repeating messages.  At most 20
# sequential messages of the same message
# category will be output to the log.
;mute 20
(设定日志信息的冗余程度。默认值为20,当相同的信息连续反复出现时,系统会去掉相同的20条)
——————————————————————————-
注意:如果不采用OpenVPN的默认路径而要定制路径的话,必须要严格确定每个配置项的路径是否设定正确。
 
在启动OpenVPN服务进程前的需要确定的工作:
1.建立配置文件中指定的日志文件,并赋予正确的权限
[root@VPNSRV01 easy-rsa]# touch /var/log/openvpn.log
[root@VPNSRV01 easy-rsa]# touch /var/log/openvpn-status.log
[root@VPNSRV01 easy-rsa]# chown nobody.nobody /var/log/openvpn.log
[root@VPNSRV01 easy-rsa]# chown nobody.nobody /var/log/openvpn-status.log
2.确定配置文件中的配置项指定的路径
例如:
比如我第一次配置完Server端启动时就失败了
[root@VPNSRV01 easy-rsa]# service openvpn start
Starting openvpn:                                          [FAILED]
查看日志寻找原因原因
[root@VPNSRV01 easy-rsa]# tail -n 10 /var/log/openvpn.log
Mon Aug 27 16:00:03 2007 OpenVPN 2.0.9 i386-redhat-linux-gnu [SSL] [LZO] [EPOLL] built on Mar  8 2007
Mon Aug 27 16:00:03 2007 Diffie-Hellman initialized with 1024 bit key
Mon Aug 27 16:00:03 2007 Cannot open file key file ‘ta.key’: No such file or directory (errno=2)
Mon Aug 27 16:00:03 2007 Exiting
原来ta密钥的路径没有写对,服务进程找不不到ta.key。因此整个服务启动失败。修正了正确的ta路径后再启动服务进程就正常了。因此,如果定制一些关键文件的路径时,一定要仔细根据定制情况正确编辑配置文件。
3.检查系统防火墙,是否为VPN开启了。
[root@VPNSRV01 easy-rsa]# iptables -A INPUT -p udp –dport 9988 -j ACCEPT
[root@VPNSRV01 easy-rsa]# iptables -A INPUT -m state –state RELATED,ESTABLISHED -j ACCEPT
检查防火墙
[root@VPNSRV01 easy-rsa]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination        
ACCEPT     udp  –  anywhere             anywhere            udp dpt:9988
ACCEPT     all  –  anywhere             anywhere            state RELATED,ESTABLISHED
4.转发开关是否打开,打开这个路由转发开关
[root@VPNSRV01 vpnkeys]# echo 1 > /proc/sys/net/ipv4/ip_forward
并且顺带将这个命令添加到启动脚本当中,使得每次系统启动的时候都会打开这个开关
[root@VPNSRV01 vpnkeys]# echo ‘echo 1 > /proc/sys/net/ipv4/ip_forward’ >> /etc/rc.d/rc.local
 
启动OpenVPN Server端的程序
[root@VPNSRV01 easy-rsa]# service openvpn start
Starting openvpn:                                          [  OK  ]
查看Server现在的网卡情况
[root@VPNSRV01 easy-rsa]# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:16:3E:4A:C2:28 
          inet addr:123.123.123.233  Bcast:123.123.123.255  Mask:255.255.255.0
          inet6 addr: fe80::216:3eff:fe4a:c228/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2059473 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1258577 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:159571429 (152.1 MiB)  TX bytes:98975611 (94.3 MiB)
lo        Link encap:Local Loopback 
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:273 errors:0 dropped:0 overruns:0 frame:0
          TX packets:273 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:40479 (39.5 KiB)  TX bytes:40479 (39.5 KiB)
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 
          inet addr:10.99.0.1  P-t-P:10.99.0.2  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
(这 个tun0设备就是OpenVPN虚拟出来的网络接口。另外需要提到的一点是,这个设备会被初始化,但是只有在OpenVPN的服务进程成功运行起来的时 候才会有这个设备,如果运行OpenVPN进程失败的话,是看不到这个设备的。也所以,当要使用OpenVPN的时候,切记要为它的网络接口开放特定的防 火墙,或者干脆关闭防火墙。否则Client是无法接入的,这里需要特别提醒。因为本人曾经卡在过这个问题上,当分析出来是防火墙的时候,比较让人感到崩 溃= =)
 
查看Server的路由
[root@VPNSRV01 easy-rsa]# route
Kernel IP routing table
Destination       Gateway         Genmask             Flags   Metric    Ref    Use Iface
10.99.0.2         *                   255.255.255.255   UH      0          0        0 tun0
123.123.123.0   *                   255.255.255.0      U       0           0        0 eth0
10.99.0.0         10.99.0.2        255.255.255.0      UG      0          0        0 tun0
169.254.0.0      *                   255.255.0.0         U       0           0        0 eth0
default            123.123.123.1   0.0.0.0               UG     0           0        0 eth0
其中10.99.0.0部分就是虚拟网络的路由。到此,OpenVPN的Server端已经基本完成。
 
将Server上之前为测试Client生成的证书密钥以及一些相关文件复制到Client端的/etc/openvpn/目录下这里,Client需要向Server得到五个重要的文件
CA证书文件               (我这里是ca.crt)
Client证书文件           (我这里是vpnclnt00.crt)
Client密钥文件            (我这里是vpnclnt00.key) 
Client的SSL证书请求文件  (我这里是vpnclnt00.csr)
ta密钥文件               (我这里是ta.key)
配置Client端的主配置文件
Client上也安装了OpenVPN的包,所以也有模版文件
/usr/share/doc/openvpn-2.0.9/sample-config-files/client.conf
这里将Client的主配置模版文件复制到OpenVPN的主配置路径下
[root@VPNCLNT00 ~]# ll /etc/openvpn/
total 48
-rw-r–r– 1 root root 1233 Aug 27 14:09 ca.crt
-rw-r–r– 1 root root  254 Aug 28 02:29 client.conf
-rw-r–r– 1 root root  636 Aug 27 14:09 ta.key
-rw-r–r– 1 root root 3537 Aug 27 14:09 vpnclnt00.crt
-rw-r–r– 1 root root  753 Aug 27 14:09 vpnclnt00.csr
-rw-r–r– 1 root root  887 Aug 27 14:09 vpnclnt00.key
可以看到在Client的主配置路径下一共有6个文件。5个是证书密钥,1个是Client端的主配置文件client.conf
现在我们来编辑客户端主配置文件client.conf
[root@VPNCLNT00 ~]# vi /etc/openvpn/client.conf
—————————————————————————-
client
(声明这个配置文件作用于客户端)
 
dev tun
(使用tun三层虚拟连接设备)
 
proto udp
(使用UDP协议)
 
remote 123.123.123.233 9988
(设定远程Server的IP地址和端口,这里要和Server对应起来。如果有多个Server可以连接的话可以配置多条remote,一行一条)
 
resolv-retry infinite
(始终重新解析Server的IP地址,如果remote后面跟的是域名,保证Server IP地址是动态的使用DDNS动态更新DNS后,Client在自动重新连接时重新解析Server的IP地址,这样无需人为重新启动,即可重新接入VPN)
 
nobind
(表示Client端不像Server端那样需要开放特定的端口,nobind的意思就是Client的不绑定特定的监听端口)
 
user nobody
group nobody
(指定OpenVPN服务进程的宿主用户)
 
persist-key
(设定连接保持密钥功能。在由于keepalive检测超时后而重新启动VPN的情况,不重新读取keys,而保留第一次使用的keys)

persist-tun
(设定连接保持在线功能。在由于keepalive检测超时后而重新启动VPN的情况,一直保持tun或者tap设备是linkup的,否则网络连接会先linkdown然后linkup)
 
ca ca.crt
cert vpnclnt00.crt
key vpnclnt00.key
(设 定CA证书、Client证书以及Client密钥文件的路径。与之前我Server端的配置不同,这里我没有写绝对路径而只是写了一些文件名。这是因为 我使用了默认的OpenVPN的主路径/etc/openvpn/。如果不是使用默认路径而是定制更改了这些文件的位置的话,那么就需要注上详细的绝对路 径了)
 
ns-cert-type server
(这一项是Server配置文件server.conf当中没有的。 Server使用build-key-server脚本什成的,在x509 v3扩展中加入了ns-cert-type选项,为的是防止黑客操纵他们的VPN Client模拟成VPN Server,然后使用他们的keys + DNS欺骗其他的Client连接他们假冒的VPN Server。因为他们的CA里没有这个扩展)
 
tls-auth ta.key 1
(设 定ta密钥的路径。

w3m 文本浏览器

Posted by jiayi | Posted in Linux | Posted on 03-10-2008

5

心血来潮,想在Linux终端下浏览网页…对w3m印象比较深,下面介绍下它的用法
补充一点,想在控制台下看图片,需要安装zhcon

Options

Command line usage is

 

    w3m [options] [file|URL]

If you specify filenames/URLs on command line, these documents are displayed. If you specify nothing, w3m reads a document from standard input and display it. If no filename and/or URLs are specified and standard input is tty, w3m terminates without displaying anything.

Options are as follows:

+<line number>
Move to the specified line.
-t width
Specify tab width. Default is 8.
-r
When displaying text/plain document, prohibit emphasis using backspace. If you don’t specify this option, “A^H_” is interpreted as underlined character and “A^HA” as a bold character.
-l number
Specify line number preserved internally when reading text/plain document fron standard input. Default is 10000.
-s
Display documents with Shift_JIS code.
-e
Display documents with EUC_JP code.
-j
Display documents with ISO-2022-JP code.
-T type
Specify document type. Without this option, document type is determined from extension of a file. If the determination fails, the document is regarded as text/plain.

Example:
Read HTML document from standard input and display it

   cat hoge.html | w3m -T text/html

Display HTML source

   w3m -T text/plain hoge.html
-m
Display document with Internet message mode. With this option, w3m determines document type from header information. It is useful when reading E-mail or NetNews messages.
-v
visual startup mode.
-B
Show the bookmark.
-bookmark file
Specify bookmark file.
-M
Monochrome display mode.
-F
Automatically render frame.
-S
Squeeze blank lines.
-X
Upon exit, do not display preserved screen.
-W
Toggle wrap search mode.
-o option=value
Specify option. The option names and values are same as that appears in ~/.w3m/config.
-cookie
Process cookies.
-no-cookie
Don’t process cookies.
-pauth username:password
Set username and password for (basic) proxy authentication.
-num
Show linenumber.
-dump
Read document specified by URL and dump formatted text into standard output. The width of the document become 80. This width can be overridden with -cols option.
-cols width
Specify document width. Used with -dump option.
-ppc count
Specify the number of pixels per character (default 8.0). Larger values will make tables narrower.
-dump_source
Read document specified by URL and dump the source.
-dump_head
Read document specified by URL and dump headers.
-dump_both
Read document specified by URL and dump headers and the source.
-dump_extra
Read document specified by URL and dump extra informations, headers and the source.
-post file
use POST method with file content.
-header string
insert string as a header.
-no-proxy
Don’t use proxy server.
-no-graph
Don’t use graphic character to draw frames.
-no-mouse
Don’t activate mouse.
-config file
specify config file.

Document color

Links and images are displayed as follows.

  Color mode Monochrome mode
links blue underline
inline images green reverse
form input red reverse

These colors can be customized using option setting command "o".


Key binding

After invocation, you can operate w3m by one-character commands from the keyboard.

Here’s the original key-binding table. If you are using Lynx-like key bindings, see the Lynx-like key binding.

Page/Cursor motion

SPC,C-v Forward page
b,ESC v Backward page
l,C-f Cursor right
h,C-b Cursor left
j,C-n Cursor down
k,C-p Cursor up
J Roll up one line
K Roll down one line
^,C-a Go to the beginning of line
$,C-e Go to the end of line
w Go to next word
W Go to previous word
> Shift screen right
< Shift screen left
. Shift screen one column right
, Shift screen one column left
g,M-< Go to the first line
G,M-> Go to the last line
ESC g Go to specified line
Z Move to the center line
z Move to the center column
TAB Move to next hyperlink
C-u,ESC TAB Move to previous hyperlink
[ Move to the first hyperlink
] Move to the last hyperlink

Hyperlink operation

RET Follow hyperlink
a, ESC RET Save link to file
u Peek link URL
i Peek image URL
I View inline image
ESC I Save inline image to file
: Mark URL-like strings as anchors
ESC : Mark Message-ID-like strings as news anchors
c Peek current URL
= Display information about current document
C-g Show current line number
C-h View history of URL
F Render frame
M Browse current document using external browser (use 2M and 3M to invoke second and third browser)
ESC M Browse link using external browser (use 2ESC M and 3ESC M to invoke second and third browser)

File/Stream operation

U Open URL
V View new file
@ Execute shell command and load
# Execute shell command and browse

Buffer operation

B Back to the previous buffer
v View HTML source
s Select buffer
E Edit buffer source
C-l Redraw screen
R Reload buffer
S Save buffer
ESC s Save source
ESC e Edit buffer image

Buffer selection mode

k, C-p Select previous buffer
j, C-n Select next buffer
D Delect current buffer
RET Go to the selected buffer

Bookmark operation

ESC b Load bookmark
ESC a Add current to bookmark

Search

/,C-s Search forward
?,C-r Search backward
n Search next
N Search previous
C-w Toggle wrap search mode

Mark operation

C-SPC Set/unset mark
ESC p Go to previous mark
ESC n Go to next mark
" Mark by regular expression

Miscellany

! Execute shell command
H Help (load this file)
o Set option
C-k Show cookie jar
C-c Stop
C-z Suspend
q Quit (with confirmation, if you like)
Q Quit without confirmation

Line-edit mode

C-f Move cursor forward
C-b Move cursor backward
C-h Delete previous character
C-d Delete current character
C-k Kill everything after cursor
C-u Kill everything before cursor
C-a Move to the top of line
C-e Move to the bottom of line
C-p Fetch the previous string from the history list
C-n Fetch the next string from the history list
TAB,SPC Complete filename
RETURN Accept