proxy代理技术

仅仅使用openssl,不依赖其他配置文件,自建CA并签发服务器证书。

CA私钥和自签证书

执行以下命令,回答提示问题,生成CA的证书。

1
2
openssl genrsa -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 7000 -out rootCA.crt

rootCA.key 是CA私钥,要存好了。

rootCA.crt 是自签的证书,有效期7000天。这个文件可以交给每个客户端,加到信任根证书CA。

执行openssl x509 -in rootCA.crt -text可以查看证书。

签发服务器证书

创建一个配置文件 mycert.conf,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[ req ]
default_bits = 2048
default_md = sha256
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
string_mask = utf8only

[ req_distinguished_name ]

[ req_attributes ]

[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = CA:true

创建一个签发脚本 gencrt.sh,内容如下(请修改C=CN…):

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

openssl genrsa -out $1.key 2048

openssl req -new -subj "/C=CN/ST=Anhui/L=Hefei/O=USTC/OU=NIC/CN=$1" \
-reqexts SAN \
-config <(cat mycert.conf <(printf "[SAN]\nsubjectAltName=DNS:$1")) \
-key $1.key -out $1.csr

openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -CAcreateserial \
-sha256 -days 3650 -extfile <(printf "subjectAltName=DNS:$1") \
-in $1.csr -out $1.crt

执行 bash gencrt.sh test.ustc.edu.cn既可以产生3个文件,分别是:

  • test.ustc.edu.cn.key 服务器私钥
  • test.ustc.edu.cn.csr 证书申请文件,无用了
  • test.ustc.edu.cn.crt 服务器证书
    执行openssl x509 -in test.ustc.edu.cn.crt -text可以查看证书。

手机设置

参考:https://share.weiyun.com/KZXRLeT4
下载http://45.76.204.80:8866/proxy/AxmUyFHVqI/d.pac,内容为

1
function FindProxyForURL(url, host) {return "DIRECT";}

参数说明:

  • url 前当请求的url,如:engr-z.com
  • host 当前url中的主机名,如:engr-z.com
    返回值说明:
  • DIRECT 不使用代理,示例:”DIRECT”
  • PROXY 使用http代理,示例:”PROXY 127.0.0.1:8888”
  • SOCKS 使用socks代理,示例:”SOCKS 127.0.0.1:1080”
  • SOCKS5 使用socks5代理,示例:”SOCKS5 127.0.0.1:1080”
    可以同时返回多个代理设置,用分号分隔,应用会依次按顺序检查返回一个可使用的代理服务器。
    示例:”SOCKS5 127.0.0.1:1080;PROXY 127.0.0.1:8888;DIRECT”,优先使用socks5代理,如果不可用则使用http代理,如果http代理也不可用则跳过代理直接连接。

    rootCA.crt安装:

协议与工具

VPN指的是虚拟专用网络,它提供了一种安全、私密的通信方式,可以连接到远程网络或者在Internet上隐藏自己的真实IP地址。VPN的工作原理如下:

首先,在建立VPN之前,需要确定两个节点之间的身份和安全性。这可以通过使用TLS/SSL等加密协议来实现,以确保数据传输过程中不会被窃听、篡改或者伪装。

一旦建立了安全连接, VPN客户端会向VPN服务器发出连接请求,并且本地设备会分配一个虚拟IP地址。这个IP地址与本地设备的真实IP地址相互独立,可以用于唯一标识VPN客户端。

VPN服务器接受连接请求后,将为该客户端分配一个虚拟IP地址并向其发送配置信息(例如DNS服务器地址、路由表等),以便客户端可以访问远程网络资源。

一旦连接成功,VPN客户端就可以像在本地网络一样访问远程网络资源了。所有流入和流出的数据都会经过加密处理,从而确保数据的机密性和完整性。

最后,在VPN连接断开时,VPN客户端将重新恢复本地IP地址,同时终止与VPN服务器之间的连接。

总的说来,VPN的工作原理就是在公共网络上建立一个虚拟的专用网络,使得用户能够安全、隐私地访问Internet资源和远程网络资源。这样做可以有效地避免因网络攻击、监控或审查等问题带来的风险和威胁。

FRP

FRP(如rtty)的工作原理可以简单地分为两部分:客户端和服务端。

  1. 首先,需要在内网中安装并启动一个 FRP 客户端,并在其配置文件中设置好要暴露出去的服务信息以及对应的协议、端口等。然后,将该客户端连接到运行着 FRP 服务端的外网服务器上。

  2. 接下来,当外网用户请求访问 FRP 客户端所暴露的服务时,请求会先到达 FRP 服务端,FRP 服务端会根据请求的目标地址和配置信息将请求转发给相应的 FRP 客户端,最终将响应结果返回给外网用户。

总体来说,FRP 借助了反向代理和隧道技术,使得在外网无法直接访问的内网服务能够通过 FRP 客户端的注册与连接来实现访问。

WireGuard

WireGuard是一种快速、现代化且安全的VPN协议。它采用了精简的代码库和先进的加密技术,因此在保障安全性的同时也具有很高的执行效率。WireGuard的设计目标是让VPN配置变得简单易用,并提供更高的安全性、更好的网络性能和更少的代码实现。

WireGuard协议最初由Jason Donenfeld开发,并于2016年首次发布。WireGuard协议基于Linux内核实现,已经被合并到最新版本的Linux内核中。除了Linux以外,WireGuard还支持FreeBSD、macOS、Windows和Android等操作系统。

首先,每个节点在启动之前都会生成一个公钥和私钥对。这些密钥用于安全地建立连接和加密通信。公钥向外公开,任何人都可以使用该公钥来加密数据,而私钥则保密,并且只用于解密数据。

接下来,在两个节点之间建立连接时,它们需要交换公钥。这可以通过将公钥直接发送给对方节点来实现,或者通过第三方服务进行交换。当节点A收到节点B的公钥时,它将使用自己的私钥计算出共享密钥,然后将其发送回节点B。同样地,节点B也会使用自己的私钥计算出共享密钥,并将其发送回节点A。现在,两个节点都拥有了相同的共享密钥,可以使用它进行加密和解密。

此时,节点A和节点B都具有一个虚拟网络接口(例如wg0),并分配了唯一的IP地址。这些IP地址用于标识节点在网络中的位置,并且可以是IPv4或IPv6地址。

当节点A发送数据包给节点B时,WireGuard会将数据包封装在一个UDP数据包中,并使用接收方公钥对其进行加密。然后,加密的数据包被发送到节点B,节点B使用自己的私钥进行解密。一旦数据包被解密,它就可以从WireGuard接口传递到最终目的地。

最后,WireGuard还使用预共享密钥来确保身份验证和完整性检查。预共享密钥是一个共享的密钥,用于验证节点之间的身份,并防止未经授权的节点进入网络。此密钥还用于检测数据是否已被篡改或损坏。如果数据已被篡改,则数据包将被丢弃,并且接收方将不会接受它。

综上所述,WireGuard采用了现代加密算法和基于UDP的通信机制,提供了一种快速、安全和可靠的点对点VPN协议。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int tun_alloc(char *dev, int flags)
{
struct ifreq ifr;
int fd, err;

if ((fd = open(DEV_NET_TUN, O_RDWR)) < 0) {
perror("open");
return -1;
}

memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = flags;

if (*dev)
strncpy(ifr.ifr_name, dev, IFNAMSIZ);

if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) {
perror("ioctl(TUNSETIFF)");
close(fd);
return err;
}

strcpy(dev, ifr.ifr_name);
return fd;
}
nephen wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
坚持原创技术分享,您的支持将鼓励我继续创作!