├── data.db 'sqlite数据库文件。若未配置mysql,默认使用sqlite,项目首次启动会自动初始化sqlite数据库。
├── docs '项目相关的一些文档
├── ├── Aop.MD '框架层Aop机制、使用说明
├── └── Channel.MD '内网穿透实现原理、代理实现流程说明
├── lib '项目开启了将自动生成的类保存到本地后,运行过程中动态生成的类自动保存到此处,方便学习、调试
├── neutrino-core '一套手写的基于netty的框架,相当于简易版的SpringBoot + Mybatis + xxljob,计划后期分离为单独开源项目维护
├── neutrino-proxy-admin '基于vue-element-admin开发的一个管理系统,用于可视化操作端口映射、代理数据实时监控
├── neutrino-proxy-client '基于netty的代理客户端,用于和服务端交互、转发内网数据
├── neutrino-proxy-core '代理相关的公共代码(协议、常量)
├── neutrino-proxy-server '基于netty的代理服务端,用于和客户段交互,将客户端转发的内网数据转发至外网端口
└── todolist.MD '近期的开发计划
复制代码
以下版本均为笔者开发时实际的使用版本
Node:v13.12.0Java:1.8.0_351Mysql:8.0.31 (非必需,使用sqlite则无需考虑数据库)Nginx:1.21.4 (非必需,可直接使用服务端项目提供的静态资源服务)可直接前往Gitee仓库发行版页面下载所需版本已打好的包。 若需手动打包,则可参照下面的执行命令:
# 服务端打包
mvn clean install -U -pl neutrino-proxy-server -am -Dmaven.test.skip=true
# 客户端打包
clean install -U -pl neutrino-proxy-client -am -Dmaven.test.skip=true
# 管理后台前端项目打包(本地环境,local改为dev则为dev环境,同时需要修改config目录下面的环境配置)
npm run build:local
复制代码
使用常规的jar包部署方式即可,如:java -jar xxxx
Nginx方式部署(推荐):
server {
listen 9527;
server_name localhost;
#开启gzip
gzip on;
#低于1kb的资源不压缩
gzip_min_length 1k;
#压缩级别1-9,越大压缩率越高,同时消耗cpu资源也越多,建议设置在5左右。
gzip_comp_level 5;
#需要压缩哪些响应类型的资源,多个空格隔开。不建议压缩图片.
gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
#配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
gzip_disable "MSIE [1-6]\.";
#是否添加“Vary: Accept-Encoding”响应头
gzip_vary on;
location / {
root /work/projects/neutrino-proxy-server/neutrino-proxy-admin/dist;
try_files $uri $uri/ /index.html;
add_header Last-Modified $date_gmt;
}
}
复制代码
在没有Nginx时,为了快速体验代理效果,可直接使用服务端项目提供的静态资源服务。 直接将neutrino-proxy-admin打包后的文件解压放在neutrino-proxy-server.jar同级别目录下即可。 例如:服务端配置的web端口为8080,则访问http://服务端IP:8080, 则会直接解析渲染neutrino-proxy-server.jar同级别目录下neutrino-proxy-admin/dist/index.html。
需要注意的是,使用服务端自带的静态资源服务时,由于框架目前未支持缓存、gzip压缩,所以访问速度没有使用nginx快,正式使用推荐用nginx。
端口池的作用是将代理服务需要对外暴露的端口进行集中管理,方便安全组设置时统一操作。
本项目为了简化首次配置,默认初始化数据会将9101~9120的所有端口加入端口池。 可以在服务端项目sql配置(port_pool.data.sql文件)中自行修改初始化数据,也可以运行后在端口池管理页面手动维护。
首次使用如果为了快速体验,建议直接使用默认端口池,则无需任何配置。
用户是登录管理后台的身份主体,同时也是持有license的身份主体,用于支持代理连接的合法性认证。
本项目为了简化首次配置,默认初始化admin、visitor两个用户,默认密码为123456。 可以在服务端项目sql配置(user.data.sql文件)中自行修改初始化数据,也可以运行后在用户管理页面手动维护。
首次使用如果为了快速体验,建议直接使用默认用户,则无需任何配置。
License是客户端连接代理服务端时所需要的唯一合法凭证,一个License同时只能被一个客户端使用。
本项目为了简化首次配置,默认为每个用户初始化了一些license。 可以在服务端项目sql配置(license.data.sql文件)中自行修改初始化数据,也可以运行后在License管理页面手动维护。
首次使用如果为了快速体验,建议直接使用默认License,则无需任何配置。
端口映射是代理的基本单元,一个外网端口在同一时刻被唯一的映射到一个内网IP+端口。所有流出该外网端口的流量都转发自对应的内网端口,同理所有流入该外网端口的流量都会转发到对应的内网端口。
本项目为了简化首次配置,默认为每个用户初始化了一些端口映射。可以在服务端项目sql配置(port_mapping.data.sql文件)中自行修改初始化数据,也可以运行后在端口映射管理页面手动维护。
首次使用如果为了快速体验,建议直接使用默认端口映射,则无需任何配置。
上述步骤完成后,就可以开始代理自己的局域网设备了。
比如现在有一个license:a123456,该license配置了一个或多个端口映射,其中包含9010到localhost:8080的映射(localhost表示代理客户端所在主机的端口,可以换成客户端所在局域网的任何IP)。此时修改客户端配置的服务端ip、license等启动客户端,就可以开启代理了,端口映射管理对应的记录在线状态为"在线"则证明代理成功建立。
该license配置也可以通过客户端启动参数、启动后引导式输入、外置配置提供,为了简化首次体验门槛,这里直接提供一个外置配置模版:
{
"jksPath":"classpath:/test.jks",
"licenseKey":"b0a907332b474b25897c4dcb31fc7eb6",
"serverIp":"localhost",
"serverPort":9002,
"sslEnable":true
}
复制代码
修改上述json中的licenseKey,serverIp、serverPort、sslEnabled后,保存文件命名为.neutrino-proxy-client.json,放在客户端当前目录下(jar包启动时,放在jar包同级别目录下。idea启动时,放在项目根目录下),然后直接启动客户端。
此时通过访问外网ip+端口,可以成功访问内网服务。通过此方式,可以代理任何基于TCP之上的协议,如:socket、websocket、http、ftp、ssh等。
篇幅所限,此处不便赘述管理后台相关的开发,有vue基础的童鞋基本都可以自行开发。服务端的初始化数据足够调试工作,开发过程无需单独在管理页面操作。
与SpringBoot项目类似,客户端、服务端项目均由一个入口类完成整个项目的启动,分别为ProxyClient、ProxyServer。
内置配置采用yml风格,主要涉及Http端口、静态资源路径、协议参数、代理服务端端口、jks证书、数据源、license等。 整个项目基于neutrino-core,风格类似于SpringBoot。笔者不喜欢因过分炫技而引入过多花式操作,因为项目的定位是个人开发者,且满足使用的同时兼顾学习其原理的需求。基本使用方式与SpringBoot类似,尽可能降低首次学习成本。
neutrino-core项目test目录下包含众多核心封装的测试代码,通过调试这些代码,能尽可能减少大家学习的障碍。
License管理:
端口映射管理:
端口池管理:
用户管理:
从2022-06-16 第一个完整可用版本发布(无管理后台、无DB,纯配置实现)起,该项目已具备完整的内网穿透功能。经过后续的不断重构,初步完成了以下迭代:
由于笔者工作之余才能进行开发,可投入时间不固定。截至目前(2023-02),该项目2.0版本仍未发布,基于此未来的计划如下:
笔者时间、能力有限,且开源项目非一朝一夕之事,存在众多问题亦在所难免。使用、学习过程中有任何问题欢迎大家与我联系。
对项目有什么想法或者建议,可以加我微信 yuyunshize 拉交流群,或者创建issues,一起完善项目
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
Arel3.0.2提供了两个类来指定连接类型:Arel::Nodes::InnerJoin和Arel::Nodes::OuterJoin并使用InnerJoin默认。foo=Arel::Table.new('foo')bar=Arel::Table.new('bar')foo.join(bar,Arel::Nodes::InnerJoin)#innerfoo.join(bar,Arel::Nodes::OuterJoin)#outerfoo.join(bar,???)#left如果要生成左连接,如何连接两个表? 最佳答案 你可以使用
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit
我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)
我正在尝试创建一个带有项目符号字符的Ruby1.9.3字符串。str="•"+"helloworld"但是,当我输入它时,我收到有关非ASCII字符的语法错误。我该怎么做? 最佳答案 你可以把Unicode字符放在那里。str="\u2022"+"helloworld" 关于ruby-如何在Ruby字符串中插入项目符号字符?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1195
有人知道如何将capybarapoltergeist的用户代理覆盖到移动用户代理以进行测试吗?我发现了一些有关为seleniumwebdriver配置它的信息:http://blog.plataformatec.com.br/2011/03/configuring-user-agents-with-capybara-selenium-webdriver/这在capybara闹鬼中怎么可能? 最佳答案 请参阅poltergeistgithub页面上的链接:https://github.com/teampoltergeist/polte
我正在使用Ruby/Mechanize编写一个“自动填写表格”应用程序。它几乎可以工作。我可以使用精彩CharlesWeb代理以查看服务器和我的Firefox浏览器之间的交换。现在我想使用Charles查看服务器和我的应用程序之间的交换。Charles在端口8888上代理。假设服务器位于https://my.host.com。.一件不起作用的事情是:@agent||=Mechanize.newdo|agent|agent.set_proxy("my.host.com",8888)end这会导致Net::HTTP::Persistent::Error:...lib/net/http/pe
我的Rails站点使用了一个确实不是很好的gem。每次我需要做一些新的事情时,我最终不得不花费与向实际Rails项目添加代码一样多的时间来为gem添加功能。但我不介意,我将我的Gemfile设置为指向我的gem的GitHub分支(我尝试提交PR,但维护者似乎已经下台)。问题是我真的没有找到一种合理的方法来测试我添加到gem的新东西。在railsc中测试它会特别好,但我能想到的唯一方法是a)更改~/.rvm/gems/.../foo。rb,这看起来不对或者b)升级版本,推送到Github,然后运行bundleup,这除了耗时之外显然是一场灾难,因为我不确定我所做的promise是否正