此篇文章只为研究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请求都是走加密隧道的,目的达成。