利用 iptables 做端口转发,实现代理中转 

最近得了一台TW 的NAT机器,考虑到是TW的原生IP,打算好好利用一番。可是直连过去丢包情况严重,考虑到我手里有一台HK的机器,到我,到TW的线路都还不错。

所以决定使用这台机器来做中转功能。这里就需要用到端口转发。

端口转发有很多解决方案,支持反代的软件有很多,比如nginx,apache,haproxy,socat 等.

这些都是应用层面的,而且得安装对应的软件包,配置,监听端口,运行才行。但是如果想到操作系统内核底层操作的话,就不得不说iptables 了。

首先修改kernel 内核参数,开启端口转发功能。

[root@hk_uc ~]# cat /etc/sysctl.conf
# sysctl settings are defined through files in
# /usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/.
#
# Vendors settings live in /usr/lib/sysctl.d/.
# To override a whole file, create a new file with the same in
# /etc/sysctl.d/ and put new settings there. To override
# only specific settings, add a file with a lexically later
# name in /etc/sysctl.d/ and put new settings there.
#
# For more information, see sysctl.conf(5) and sysctl.d(5).
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.unknown_nmi_panic = 0
kernel.sysrq = 1
fs.file-max = 1000000
vm.swappiness = 10
fs.inotify.max_user_watches = 10000000
net.core.wmem_max = 327679
net.core.rmem_max = 327679
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
fs.inotify.max_queued_events = 327679
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.neigh.default.gc_thresh1 = 2048
net.ipv4.neigh.default.gc_thresh2 = 4096
net.ipv4.neigh.default.gc_thresh3 = 8192
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv4.ip_forward = 1 //开启端口转发 1=>开启 0=>关闭

编辑保存后,重载配置,使之生效。

[root@hk_uc ~]# sysctl -p
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.unknown_nmi_panic = 0
kernel.sysrq = 1
fs.file-max = 1000000
vm.swappiness = 10
fs.inotify.max_user_watches = 10000000
net.core.wmem_max = 327679
net.core.rmem_max = 327679
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
fs.inotify.max_queued_events = 327679
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.neigh.default.gc_thresh1 = 2048
net.ipv4.neigh.default.gc_thresh2 = 4096
net.ipv4.neigh.default.gc_thresh3 = 8192
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv4.ip_forward = 1


接下来就是操作iptables,加入相关的转发规则链。现在比较主流的方式通过 前置路由链、和后置路由链 的方式去实现转发。

我现在要把HK机器9800 端口上进来的TCP请求,统统转发到TW机器(210.203.57.103)的19600 端口上去。
加入前置路由规则:

iptables -t nat -A PREROUTING -p tcp -m tcp --dport 9800 -j DNAT --to-destination 210.203.57.103:19600

加入后置路由规则:

iptables -t nat -A POSTROUTING -d 210.203.57.103 -p tcp -m tcp --dport 19600 -j SNAT --to-source 10.8.32.28

10.8.32.28 是我的网卡eth0 IP.

[root@hk_uc ~]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1454
inet 10.8.32.28 netmask 255.255.0.0 broadcast 10.8.255.255
ether 52:54:00:1a:5d:55 txqueuelen 1000 (Ethernet)
RX packets 83091504 bytes 30721120125 (28.6 GiB)
RX errors 0 dropped 891 overruns 0 frame 0
TX packets 98367783 bytes 33007019179 (30.7 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 14612734 bytes 19897570061 (18.5 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 14612734 bytes 19897570061 (18.5 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

到这步,iptables 端口转发就已经配置好了。保存下iptables 配置。

[root@hk_uc ~]# iptables-save
# Generated by iptables-save v1.4.21 on Fri Jan 3 11:52:32 2020
*nat
:PREROUTING ACCEPT [7618:365173]
:INPUT ACCEPT [7618:365173]
:OUTPUT ACCEPT [1727:118684]
:POSTROUTING ACCEPT [1727:118684]
-A PREROUTING -p tcp -m tcp --dport 9800 -j DNAT --to-destination 210.203.57.103:19600
-A PREROUTING -p tcp -m tcp --dport 9900 -j DNAT --to-destination 140.238.11.39:9600
-A POSTROUTING -d 210.203.57.103/32 -p tcp -m tcp --dport 19600 -j SNAT --to-source 10.8.32.28
-A POSTROUTING -d 140.238.11.39/32 -p tcp -m tcp --dport 9600 -j SNAT --to-source 10.8.32.28
COMMIT
# Completed on Fri Jan 3 11:52:32 2020
# Generated by iptables-save v1.4.21 on Fri Jan 3 11:52:32 2020
*filter
:INPUT ACCEPT [433680:111523114]
:FORWARD ACCEPT [360898:155486678]
:OUTPUT ACCEPT [476261:116542832]
COMMIT
# Completed on Fri Jan 3 11:52:32 2020

至此,所有操作完成。可以看到HK 机器的9800端口已经可以ping 通了。我本地到TW机器的延迟约等于 本地到HK + HK 到 TW 的延迟总和。牺牲一点延迟,换来线路的稳定,也是值得的。

本文在实践撰写的过程参考一下文章:
http://xstarcd.github.io/wiki/Linux/ipt ... share.html
https://coolnull.com/3322.html
https://doubibackup.com/3we1qxzj-3.html
[ ] ( 1141 次浏览 ) 永久链接 ( 2.7 / 1714 )
在NAT机器上搭建 shadowsocks + v2ray-plugin (websocket SSL) 组合 

最近入了一台套路云的TW NAT机器,就寻思着把它搭建起来用于代理,本来打算是还用v2ray websocket + caddy 那套,不过由于是NAT机器,80,443 这样的端口基本是不用想了,我还得去研究caddy 第三方SSL证书怎么配置使用、还得去freessl.org 这样的网站自己去生成一套SSL证书。因为caddy 的自动签名证书只能用在常规的https 443端口。

想想就麻烦。但是shadowsocks 基于我之前使用情况,发现已经大概率被识别了。在这种情况下,我想试试之前听说过,但一直没用过的 v2ray-plugin 插件.

如果你的机器没有golang 环境,请先安装并配置好GOPATH、PATH.参见:https://go-repo.io/
最好也安装一下开发者套件,比如 yum groupinstall 'development tools'
确认防火墙已经关闭,或者指定端口已经放行.比如 systemctl stop firewalld

首先下载 go-shadowsocks2,

go get -u -v github.com/shadowsocks/go-shadowsocks2

一行命令搞定。

接下来是v2ray-plugin.(它的项目主页提供了bin 包下载。图省事的可以直接下载解压,复制到PATH目录即可。)

git clone https://github.com/shadowsocks/v2ray-plugin.git

签出代码,进入目录。编辑里面的 build-release.sh 文件,删除除了 linux,x64 之外的所有系统平台、架构。下面的几个ARM 平台的也删了。
运行 build-release.sh 编译文件,完成后你会在当前目录看到适合你平台架构的可执行文件。

复制到PATH 目录下,改名为 v2ray-plugin.

mv v2ray-plugin_linux_amd64 ~/go/bin/v2ray-plugin


按说到这里就差不多了,但是因为需要跑websocket + SSL.还需要一个 SSL证书。
用到了acme.sh 工具。

git clone https://github.com/Neilpang/acme.sh

签出代码,进入目录。
因为是NAT模式,所以一般的 --standalone 模式是行不通的。(我试过给 --httpport 参数,没效果)
故而使用 DNS 验证模式,执行脚本

./acme.sh --issue --dns -d tw.xzx.im --yes-I-know-dns-manual-mode-enough-go-ahead-please

之后进入自己的DNS SERVER ISP 后台,添加一条TXT记录,内容就是脚本返回里面的。不难找~
确认域名记录生效后,再次执行脚本:

./acme.sh --renew --dns -d tw.xzx.im --yes-I-know-dns-manual-mode-enough-go-ahead-please

不出意外,基本就成功了。SSL证书的公私钥啥的就都保存到本地的 ~/.acme.sh 目录下了。

证书搞定后就起服务了。

nohup go-shadowsocks2 -password ***** -plugin v2ray-plugin -plugin-opts "server;tls;host=tw.xzx.im" -s ":9600" &

htop 看一下,服务已经起来了,go-shadowsocks 成功的调起了 v2ray-plugin 进程。

|-go-shadowsocks2,29874 -password ***** -plugin v2ray-plugin -plugin-opts server;tls;host=tw.xzx.im -s :9600
| |-v2ray-plugin,29879
| | |-{v2ray-plugin},29881
| | |-{v2ray-plugin},29882
| | |-{v2ray-plugin},29883
| | |-{v2ray-plugin},29884
| | |-{v2ray-plugin},29885
| | |-{v2ray-plugin},29886
| | |-{v2ray-plugin},30461
| | |-{v2ray-plugin},30462
| | `-{v2ray-plugin},30476
| |-{go-shadowsocks2},29875
| |-{go-shadowsocks2},29876
| |-{go-shadowsocks2},29877
| |-{go-shadowsocks2},29878
| |-{go-shadowsocks2},29880
| |-{go-shadowsocks2},30458
| |-{go-shadowsocks2},30459
| |-{go-shadowsocks2},30464
| |-{go-shadowsocks2},30477
| |-{go-shadowsocks2},30699
| |-{go-shadowsocks2},30701
| `-{go-shadowsocks2},30710

端口监听正常.

[root@vm1219610 ~]# netstat -nlp | grep 9600
tcp 0 0 0.0.0.0:9600 0.0.0.0:* LISTEN 29879/v2ray-plugin
udp 0 0 0.0.0.0:9600 0.0.0.0:* 29874/go-shadowsock


服务端搞定了。接下来配置一下自己本地的代理工具,我用的是netch,GUI 上添加一个新SS服务器,配置一下就OK了。

{
"Remark": "TW",
"Group": "None",
"Type": "SS",
"Rate": 1.0,
"Hostname": "tw.xzx.im",
"Port": 19600, #这里是NAT端口转发的外网开放端口
"Username": null,
"Password": "*******",
"UserID": "",
"AlterID": 0,
"EncryptMethod": "chacha20-ietf-poly1305",
"Plugin": "v2ray-plugin",
"PluginOption": "tls;host=tw.xzx.im",
"Protocol": null,
"ProtocolParam": null,
"OBFS": null,
"OBFSParam": null,
"TransferProtocol": "tcp",
"FakeType": "",
"Host": "",
"Path": "",
"QUICSecure": "none",
"QUICSecret": "",
"TLSSecure": false,
"Delay": 49
}


这是我netch 的json 配置,仅供参考。

注:本文在实践、撰写时参考了一下项目文档:
https://github.com/shadowsocks/go-shadowsocks2/blob/master/README.md
https://github.com/shadowsocks/v2ray-plugin/blob/master/README.md
https://github.com/Neilpang/acme.sh/blob/master/README.md
[ ] ( 1160 次浏览 ) 永久链接 ( 2.7 / 1782 )
搭建经典的 v2ray + tls websocket + caddy https 组合 

最近入手了一台 浩航互联(贵州才智浩航网络科技有限公司)的香港沙田机房的VPS,PCCW 线路,延迟很是感人。月租也不贵,打完折也就34块钱左右。很是兴奋~

不过用了一段时间,发现用来做网站(比如我在上面搭的IPA server) 是很不错,访问也算给力。就是偶尔也需要用它来翻个墙啥的就感觉不给力了。单纯的google search 还说得过去,要是想看个youtube 720/1080p 的就感觉垃圾的不行。

按说带宽也没那么差,估计是被运营商QOS了。所以思索了一下,决定给v2ray 上一套混淆。

我当前的v2ray 是最简单的配置,tcp 跑法,无混淆,直接监听外网端口。考虑我本身也在用caddy web server(ipa OTA 强制要求HTTPS),所以干脆就上了v2ray + websocket + caddy 这套经典架构。

首先先从 v2ray json conf 动刀,修改完配置如下:

[root@HongKong ~]# cat /etc/v2ray/config.json
{
"inbounds": [{
"port": 9700,
"listen": "127.0.0.1",
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "UUID_STR***************",
"level": 1,
"alterId": 64
}
]
},
"streamSettings": {
"network": "ws",
"security": "none",
"tlsSettingsOmit": {
"serverName": "hh.xzx.im",
"allowInsecure": false
},
"wsSettings": {
"path": "/caonima",
"headers": {
"Host": "hh.xzx.im"
}
}
}
}],
"outbounds": [{
"protocol": "freedom",
"settings": {}
},{
"protocol": "blackhole",
"settings": {},
"tag": "blocked"
}],
"routing": {
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "blocked"
}
]
}
}


由于我的v2ray 是要作为后置实例跑在caddy 后面的,所以不需要自行校验TLS/SSL 证书的合法性,也就是说 v2ray 和 caddy 的内部通讯是无加密的。
所以 security 字段设为 none 即可。(不依赖caddy 等反代服务器,直接对外提供服务的,需要设成 tls).
那么 tls 相关的配置项 tlsSettings 其实也是不需要的,我懒得删除,就直接把key 名称重命名为一个无意义的名字。。。。

wsSettings 这个字段还是很重要的,按照服务器情况设置即可。

v2ray 的配置搞定后,就是改caddy 的配置,我的这台caddy 跑了一个ipa server,已经反代了一台 nodejs 实例。所以要额外做点手脚。修改完的配置如下:

[root@HongKong ~]# cat /etc/caddy/Caddyfile
hh.xzx.im {
root /root/ipa-server/upload
rewrite {
if {path} is /
# proxy v2ray first
if {path} not /caonima
to /proxy/{uri}
}
rewrite {
# proxy v2ray first
if {path} not /caonima
to {path} /proxy/{uri}
}
proxy /proxy 127.0.0.1:8080 {
#except /proxy
without /proxy
#transparent
}
proxy /caonima 127.0.0.1:9700 {
#preset websocket
websocket
header_upstream -Origin
}
}


我单独开了一个 /caonima 的二级路径去反代转发到 v2ray 的流量,其他的保持不变。

如果你是新安装的caddy 或者 你打算用一个新的域名单独去做反代,那么配置上则不需要这么麻烦。

直接

xxx.domain.tld {
proxy / 127.0.0.1:PORT### {
websocket
header_upstream -Origin
}
}


这样即可。简单明了~

两个配置都改好后,都重启下各自的进程基本就生效了。接下来就是客户端怎么用最新的配置连过去了。

每个版本的客户端设置的方式/界面大同小异。我用的是 V2RayX - GUI for V2Ray on macOS. 我觉得挺不错的,很棒。

基本的套路就是 先把端口号改了 因为是 https ,改成 443.
然后是协议,之前是 tcp,现在是 websocket.
最后是 websocket 和 TLS 证书 的一些设置,指定正确的 hostname即可。
UUID 啥的,因为都没动,所以不用改。

我的改完的配置如下(主要是出站的节点配置):

{
"outbounds": [{
"sendThrough": "0.0.0.0",
"mux": {
"enabled": false,
"concurrency": 8
},
"protocol": "vmess",
"settings": {
"vnext": [{
"address": "hh.xzx.im",
"users": [{
"id": "UUID_STR*********************",
"alterId": 64,
"security": "auto",
"level": 1
}],
"port": 443
}]
},
"tag": "HongKong",
"streamSettings": {
"wsSettings": {
"path": "\/caonima",
"headers": {
"Host": "hh.xzx.im"
}
},
"tlsSettings": {
"allowInsecure": true,
"alpn": [
"http\/1.1"
],
"serverName": "hh.xzx.im",
"allowInsecureCiphers": true
},
"security": "tls",
"network": "ws"
}
}]
}


保存配置,打开 https://www.google.com/, 加载完成。嗯,看起来一切OK.
我还测试了一下 youtube.com,速度果然有了很大的改善…… 真的是醉了~

本文撰写和实践时参考了以下文章:
https://v2ray.com/chapter_02/01_overview.html
https://www.feiqy.com/v2ray-best-config/
https://caddy.community/t/how-to-set-proxy-except-root-directory/3008
[ ] ( 1211 次浏览 ) 永久链接 ( 2.9 / 1509 )
解决 caddy http server 没有 try_files 标识符 的坑逼问题 

最近由于想给老的ipad mini 1 安装微信,由于app store 里面的最新版本已经不兼容mini 1 了,便打算自己搭建一个 https://www.diawi.com/ 这样的ipa server.

在github 找到了一个国人开发的nodejs 版本的。前端用一台web server 反代node 后段。本来想用nginx的,毕竟方便。不过因为坑爹的苹果要求站点必须有SSL证书,所以便选择了自带SSL续期的caddy server.不过倒也方便。

都下载,安装,配置,部署后,发现一切ok,就是安装不了。

很是奇怪,于是下载了app 对应的plist文件(https://hh.xzx.im/plist/ce4b37087f3b429d.plist),打开看了一下。

发现由于是反代,里面的url 都是 127.0.0.1/xxx 这样的。。。

编辑 config.js 把publicURL 改成外网caddy 的入口地址.如下:

[root@HongKong ~]# cat ipa-server/config.js
const path = require('path')

module.exports = {
debug: process.env.NODE_ENV !== 'production',
host: "0.0.0.0",//process.env.HOST || '0.0.0.0',
port: "8080",//process.env.PORT || 8080,
publicURL: "https://hh.xzx.im",//"process.env.PUBLIC_URL,
uploadDir: process.env.UPLOAD_DIR || path.resolve(__dirname, 'upload'),
}


重启node,发现还是不能安装...诧异~~~

试着下载了下plist 文件中的ipa 包,提示 404 not found.

这才恍然大悟,原来caddy 的反代没有本地文件(夹)优先的策略,一股脑全部发给node 了。

网上查阅了相关资料,发现很多人都这个需求,也提供了对应的解决方案,修改caddyFile 配置,如下:

[root@HongKong ~]# cat /etc/caddy/Caddyfile
hh.xzx.im
root /root/ipa-server/upload
rewrite {
if {path} is /
to /proxy/{uri}
}
rewrite {
to {path} /proxy/{uri}
}
proxy /proxy 127.0.0.1:8080 {
#except /proxy
without /proxy
#transparent
}


保存配置后,systemctl restart caddy 重启caddy.再次尝试下载,下载对话框弹出来了,ok,完美~

确认一切正常后,ctrl + c 退出 npm start 控制台。

使用 nohup node index.js & 命令已后台方式运行 ipa-server.

本文撰写时参考了以下文章:
https://github.com/iineva/ipa-server
https://github.com/mholt/caddy/issues/695
https://caddy.community/t/unable-to-access-root-path-when-using-systemd/756
https://caddy.community/t/caddy-try-files/3248/5
[ ] ( 1285 次浏览 ) 永久链接 ( 2.8 / 1586 )
终于把网站烦人的丢失登录状态的问题给干掉了 CAO 

这小博客自从套了cloudflare 的cdn 后我就一直觉得很奇怪,每次的登陆状态很不稳定,点一下按钮身份变成游客了,再刷新一下又变回来了。再刷新一下,又tmd 回去了。。。。

所以,每次写好文章后,都是习惯性的ctrl + c 保存一下,免得点击一下提交按钮直接让我重新登录了。千辛万苦码的字直接消失了。。。

至于原因,其实我大概已经猜到了,应该是CF 这边的ip 池的问题,每次随机策略分配过来的ip不固定,就导致了这样的人间惨剧。

今天正好有空就找一下代码块的位置,把它修复了。

如图(完全印证了我的想法):







保存退出,登录一下后台,拼命的狂按F5,嗯,不错,状态没掉。
[ ] ( 1428 次浏览 ) 永久链接 ( 2.8 / 1500 )

<< <上一页 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 下一页> >>