我用 Linux网络技术python

使用frp实现内网穿透

2018-07-12  本文已影响18人  飞不起来的

现在办理宽带的时候,运营商都不会给你分配公网静态ip,这导致的问题就是如果你想让外部网络访问家里局域网内的某台设备,你不能使用一般路由器都自带的端口映射(虚拟服务器)来简单的让外部网络成功访问到。在运营商动态分配ip的时候,如果动态分配到的ip是公网ip,那么可以使用一些收费的DDNS动态域名解析服务来访问内网中的web服务,这时候路由器的端口映射也是需要配置的。如果动态分配到的ip不是公网ip,那么DDNS也不会灵光了。我们需要彻底一点的方案,那就是内网穿透,即通过一台具有公网静态ip的电脑(服务器,vps等),来反向代理内网中的机器。

怎么样来理解通过反向代理穿透到内网呢,首先我们需要在具有公网静态ip的服务端,安装一个代理服务(例如本文将要提到的frp的服务端frps),然后在内网的设备上安装此代理服务的客户端,服务端跟客户端都作为后台服务启动运行(服务端首先启动运行),客户端连接到代理服务的端口,此时我们的服务端作为反向代理服务器已经可以接受来自互联网的请求了,并能够把请求转发到客户端上设置好的相应端口(服务,例如web)上。简而言之,现在我们可以从外部网络访问内网中的某些设置好的设备了。

前些日子,我想要在上班的时候也能访问家里的刷好openwrt的路由器的设置界面及ssh服务,所以通过google,最终我决定使用frp这个开源软件,下面是github上的项目主页:
https://github.com/fatedier/frp
更多配置请访问项目主页自行研究。

折腾过程记录:

前提:

服务端配置

首先从此处找到适合自己系统架构的编译好的软件包,点击右键,从弹出菜单中找到复制链接地址单击复制。

支持systemd的linux系统(ubuntu,centos7)

我使用的是centos7的vps,通过ssh登陆进去,使用wget命令行工具把软件包下载到 /opt目录下。

cd /opt
sudo wget 粘贴复制的链接

这时候将下载到的软件包进行解压。

ls
sudo tar xzvf  软件包名

解压成功后进入刚刚解压的文件目录。

ls
cd 刚解压的目录
ls

可以看到frpc,frps,frpc_full.ini,frps_full.ini,frpc.ini,frps.ini等文件,frps是服务端二进制程序,frpc是客户端二进制程序,frps.ini是服务端的配置文件,frpc.ini是客户端的配置文件,frps_full.ini跟frpc_full.ini是示例配置文件。


在centos7下,可以通过systemd来管理守护进程,根据此github项目上issue上vc5写的systemd 的service文件修改了一份frps程序可用的service文件,文件名改为frps.service,放在 /usr/lib/systemd/system/目录下。
sudo cd /usr/lib/systemd/system
sudo vim frps.service

输入上一行命令后,进入空的frps.service文件,点击i进入编辑模式,复制粘贴下面的内容

[Unit]
Description=frps daemon
After=syslog.target  network.target
Wants=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.ini
Restart= always
RestartSec=1min
ExecStop=/usr/bin/killall frps

[Install]
WantedBy=multi-user.target

根据frps.service中启动frps的那一行(ExecStart=......),将frps跟frps.ini移动或者复制到相应的目录下。到这一步就可以把下载的软件包跟解压出来的文件夹删除了。

cd /opt/frp文件夹名/
sudo cp frps /usr/local/bin#复制到该目录下
sudo mkdir /etc/frp#新建文件夹frp
sudo cp frps.ini /etc/frp/#复制到该目录下
sudo rm -rf 软件包 解压出来的文件夹

现在来设置/etc/frp目录下的frps.ini,通过cd /etc/frp切换到该目录下,输入vim frps.ini 命令修改frps.ini,我的配置如下:

#frps.ini
[common]
bind_port = 1978#可以自行设定

vhost_http_port = 8081#可以自行设定
vhost_https_port = 4433#可以自行设定

token=jsljgslaljglsgsgjlsjgslgjs#请自己设置密钥
authentication_timeout=0#假如服务端与客户端的时间相差超过24小时,可能会无法连接,此处设置为0,将不再验证服务端与客户端时间

log_file = ./frps.log
log_level = info
log_max_days = 3

subdomain_host = example.com#填写自己的域名,此处填写subdomain_host则代理http,https协议时客户端在web代理中要填写subdomain项目

修改好frps.ini,服务端的配置基本完成,通过如下命令启动运行:

sudo systemctl  enable frps.service#允许开机自启
sudo systemctl  start frps.service#启动
sudo systemctl  status frps.service#查看运行状态

如果使用防火墙firewalld,frps相关服务端口可能并未开放,可以通过如下命令开放相关端口:

sudo firewall-cmd --permanent --add-port=相关服务端口/tcp #此处端口是配置文件中设置好的端口,bind_port,vhost_http_port,vhost_https_port ,还有客户端配置文件中的远程端口,请逐条添加
sudo firewall-cmd --reload

客户端配置

客户端的配置前面几步跟服务端类似,首先从此处找到适合自己系统架构的编译好的软件包并下载下来。

openwrt(LEDE)系统的路由器

把frpc复制到/usr/bin/目录,把frpc.ini复制到/etc/目录,根据网络上的教程,我尝试了在web管理界面中添加到本地启动脚本中,输入

nohup frpc -c /etc/frpc.ini > /dev/null 2>&1  &

但这样开机启动的方式并不起作用。所以我用python编写了一个监测frpc是否运行的脚本,如果脚本检测到frpc没有运行就会启动frpc。将该脚本命名为monitor.py,放在/root目录下,内容是这样的:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import time

cmd="ps |grep frp |grep -v grep"
process=os.popen(cmd).readlines()
if process:
   time_now=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
   with open("monitor.log","at") as f:
        f.write(time_now+" running\n")
        for line in process:
            f.write(line)
else:
   time_now=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
   with open("monitor.log","at") as f:
        f.write(time_now+" no running\n")
   os.popen("frpc -c /etc/frpc.ini >/dev/null 2>&1 &")

将monitor.py赋予执行权限

chmod a+x monitor.py

我们可以在linux的计划任务cron中每十分钟运行一次脚本,我们在/etc/crontabs/root文件的末尾添加上一条计划任务

*/10 * * * * /root/monitor.py

客户端配置文件frpc.ini:

[common]
server_addr = 0.0.0.0#填写自己服务器ip
server_port=1978 #可以自行设定
token=sgfsgsgshshshshshshshs #跟服务端必须一致

[ssh_router]#ssh连接
type = tcp
local_ip = 127.0.0.1
local_port = 22 #可以自行设定
remote_port=4555#可以自行设定

[web_router]#登录web
type=http#或者https
local_ip=127.0.0.1
local_port =80#可以自行设定
#此处无需设定远程端口,服务端配置里已经设置了vhost_http_port或vhost_https_port的端口
#如果服务端设置了subdomain_host,这里设置subdomain,如果服务端没有设置subdomain_host,这里设置custom_domains
subdomain=router
#custom_domains = router.example.com

当客户端配置文件修改好了,可以输入 frpc -c /etc/frpc.ini测试能否连接服务端,如下图所示说明配置正确连接成功了。

frp客户端成功连接服务端
现在重启openwrt路由器,过几分钟监测脚本运行后就可以从外网登陆路由器web界面了。前面的内容也适用于没有使用systemd的其他linux系统。
支持systemd的linux系统(ubuntu,centos7)

客户端配置跟服务端几乎一样,只需要注意两点,第一点就是编写service文件时把 frps替换成frpc,第二点就是使用客户端的配置文件frpc.ini。

欢迎浏览我的个人博客,https://diwugebingren.github.io

欢迎关注我的公众号
上一篇下一篇

猜你喜欢

热点阅读