利用OpenVPN实现...

此篇文章只为研究OpenVPN,不为其他目的
早些时候有试过用OpenVPN去实现一些需求,但最终被墙。之前在项目上又用上了OpenVPN,实现的灵感也来自项目。下面具体介绍下如何修改,其实原理很简单。

OpenVPN的源码以及如何编译安装,都在之前的文章《OpenVPN的编译安装、配置、使用及注意事项》中详细说过,在这里就直接说需要修改哪些东西了

进入OpenVPN源码目录(解压完后进入xxx/openvpn-2.4.6/src/openvpn目录下)找到以下几个文件,并做相应修改(这里为什么这样修改只是提供了一个思路,大家灵活变通)

1、进入socket.c文件,找到link_socket_read_tcp,做如下修改:

int
link_socket_read_tcp(struct link_socket *sock,
                     struct buffer *buf)
{
    int len = 0;

    //add myself
    unsigned int i;

    if (!sock->stream_buf.residual_fully_formed)
    {
#ifdef _WIN32
        len = socket_finalize(sock->sd, &sock->reads, buf, NULL);
#else
        struct buffer frag;
        stream_buf_get_next(&sock->stream_buf, &frag);
        len = recv(sock->sd, BPTR(&frag), BLEN(&frag), MSG_NOSIGNAL);

        //add myself
        for(i = 0; i <= BLEN(&frag); ++i)
        {
             *(BPTR(&frag) + i) ^= 0xff;
        }
#endif

        if (!len)
        {
            sock->stream_reset = true;
        }
        if (len <= 0)
        {
            return buf->len = len;
        }
    }

    if (sock->stream_buf.residual_fully_formed
        || stream_buf_added(&sock->stream_buf, len)) /* packet complete? */
    {
        stream_buf_get_final(&sock->stream_buf, buf);
        stream_buf_reset(&sock->stream_buf);

        return buf->len;
    }
    else
    {
        return buf->len = 0; /* no error, but packet is still incomplete */
    }
}  

2、进入socket.h文件,找到link_socket_write_tcp_posix,做如下修改:

static inline size_t
link_socket_write_tcp_posix(struct link_socket *sock,
                            struct buffer *buf,
                            struct link_socket_actual *to)
{
    //add myself
    unsigned int i;
    for(i = 0; i <= BLEN(buf); ++i)
    {
        *(BPTR(buf) + i) ^= 0xff;
    }

    return send(sock->sd, BPTR(buf), BLEN(buf), MSG_NOSIGNAL);
}  

配置文件的话,只要在Server端增加以下两条即可:

#重定向网关,因为需要另一边所有的服务器ip,所以直接将OpenVPN作为全局的隧道(可以理解为Shadowsocks中的全局代理)
push "redirect-gateway def1 bypass-dhcp"  

#推送DNS,使得客户机可以正常解析域名  
push "dhcp-option DNS 108.61.10.10"

之后在编译安装即可,这样修改后就可以支持tcp的链接了,速度比做代理快。在我机子上试出现推送DNS不生效的情况,没有时间去查具体原因,暂时需要用的时候就修改客户机的/etc/resolv.conf文件,手动切换DNS(不用了记得切换回来),可以看出用OpenVPN的话DNS请求都是走加密隧道的,目的达成。