乱码三千 – 分享实用IT技术

乱码三千 – 码出一个新世界


  • 首页

  • 归档

  • 搜索

iOS逆向篇-Clang交叉编译

发表于 2022-09-27

本篇我们的目标是在IPHONE上运行ARM64,C语言,C++和OC程序!

  1. Clang
    对于iOS开发者来说,Clang编译器一点也不陌生,Clang是一个C语言、C++、Objective-C、C++语言的轻量级编译器。源代码发布于BSD协议下,是基于LLVM的,也是Xcode 第一的编译器。
  2. 交叉编译
    指在一个平台上生成另一个平台上的可执行代码。现在我们就在Mac上写代码,在iPhone上运行,想想都刺激!
  3. 设备环境
    使用的是Mac和越狱iOS13.2.2的iPhoneX

ARM64

  1. 新建一个hello.txt文本
  2. 把下面代码复制进去,保存退出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.extern _printf
.align 4

.text
.global _main

_main:

stp x29, x30, [sp,#-0x10]! ;保存 x29 和 x30 寄存器到栈,!用来控制基址变址寻址的最终新地址是否进行回写操作
mov x29, sp ;将 sp 寄存器放入 x29 寄存器
sub sp,sp,#0x20 ;分配栈空间

adr x0,msg ;第一个参数
bl _printf

add sp,sp,#0x20 ;释放栈空间
mov sp,x29 ;将 x29 给 sp
ldp x29,x30,[sp],0x10 ;出栈给 x29 和 x30

ret ;返回

msg:
.asciz "Hello,world!\n" ; data段有一个标号msg,代表字符串"Hello,world!\n"的首地址,类型为.asciz的字符串
  1. 改文本后缀,改为hello.asm文件
  2. 打开终端,使开始编译
1
2
3
4
5
6
7
8
9
1、查看sdk安装路径
$xcrun --sdk iphoneos --show-sdk-path

2、clang编译
clang -arch arm64 -isysroot "sdk" -o hello hello.asm

// "-arch arm64" 指定框架
// " -isysroot" 指定sdk
// "-o" 输出目标文件
  1. 签名,在iOS系统中运行程序需要代码签名,所以要增加一个签名步骤。
    a.新建ent.plist
    b.把下面代码复制进去,保存在hello.asm同一目录下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>platform-application</key>
<true/>
<key>com.apple.springboard.debugapplications</key>
<true/>
<key>run-unsigned-code</key>
<true/>
<key>get-task-allow</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
</dict>
</plist>
12345678910111213141516
  1. 对hello文件进行签名
1
2
codesign -s - --entitlements ent.plist -f hello
1

在这里插入图片描述

  1. 把签名后的hello文件拷进iPhone的/usr/bin/目录下,好像很多目录下都可以的
1
2
scp hello root@192.168.0.170:/usr/bin
1

在这里插入图片描述)在这里插入图片描述

  1. 运行hello文件,完美!

在这里插入图片描述)在这里插入图片描述

———————-华丽的分割线————————

C语言

  1. 新建1.txt
  2. 复制代码保存,文件改为1.c
1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main()
{
printf("C:Hello, World! \n");

return 0;
}
12345678
  1. 编译签名

在这里插入图片描述

  1. 拷贝到iPhone上,运行, 完美!

在这里插入图片描述)img

———————-华丽的分割线————————

OBJECT-C

  1. 新建2.txt
  2. 复制代码保存,文件改为2.m
1
2
3
4
5
6
7
8
9
10
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"OC:Hello World!");
}
return 0;
}
123456789
  1. 编译签名
    oc的编译有点不一样,因为导入了foundation框架,在Clang编译的时候需要指定一下
1
2
clang -arch arm64 -framework Foundation -isysroot "sdk" 2.m -o 2
1

在这里插入图片描述

  1. 拷贝到iPhone上,运行, 完美!

在这里插入图片描述)img

———————-华丽的分割线————————

C++

  1. 新建3.txt
  2. 复制代码保存,文件改为3.cpp
1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;
int main()
{
cout << "C++:Hello, world!" << endl;
return 0;
}
1234567
  1. 编译签名
    因为clang完美兼容g++,gcc,所以一些命令可以完美继承!
    在这里插入图片描述
  2. 拷贝到iPhone上,运行, 完美!

在这里插入图片描述)img
———————-华丽的分割线————————

好了,今天的代码就敲到这里了,更多Clang的用法可以去看看文档。
文档:http://clang.llvm.org/docs/UsersManual.html

本文转载自: CSDN

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用Gradle将lua源码构建编译成可执行文件

发表于 2022-09-26

前言

对于lua的构建 官方默认使用make工具, 常见的构建工具有:

  • Make:又指GNU Make, 是Linux系统下的通用构建工具, 延伸的构建工具还有nmake, dmake, cmake, xmake等等
  • Scons: 以python语言编写的一款跨平台构建工具 对标make 容易学习快速上手
  • Ant: 基于java的构建工具, 被认为是make工具的替代品, 早期eclipse采用的构建工具就是它
  • maven: 同样是基于java, 它不单单是构建工具 还是项目管理工具, 属于Ant进化版, 目前Idea平台中 java的构建基本用的就是它
  • Gradle: 基于Groovy的构建工具, 被认为是Ant和Maven的替代品, 目前Android编译使用的构建工具就是它

什么是构建工具

以java程序为例, 我们在写好代码后, 需要使用javac指令对源码进行编译, 然后使用java指令执行

这个过程叫做编译, 如果一两个文件还好, 代码文件一多, 手动敲指令进行编译是会死人的🤪, 于是乎自动化的构建工具出现了, 目的就是为了取代人工编译

构建工具的发展

早期的make–>java的ant–>后来的maven–>现在的gradle

每一代构建工具的诞生, 都是为了解决上一代工具存在的痛点

Gradle, 用过的都说好!!😆

对Lua源码进行构建编译

我这边直接使用Android Studio, 具体步骤如下:

  1. 首先 去lua官网下载源码, 这里我使用的是5.4的源码

    lua官网

    image-20220926170825041

  2. 然后 在Studio中新建一个空工程, 然后将lua源码拖进src目录中

    image-20220926163907555

  3. 紧接着 对build.gradle文件进行配置

    lua一共包含两个可执行文件, 一个是lua另一个是luac, 所以这两个执行文件我们需要分开构建, 具体的gradle配置如下:

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    apply plugin: 'c'  //使用c构建模式


    model {

    components {
    //创建一个lua执行文件构建入口
    lua(NativeExecutableSpec) {
    sources {
    c {//指定源码位置以及需要包含和排除的问价
    source {
    srcDir "src/main/c/lua"
    include '*.c'
    exclude 'luac.c'
    }
    exportedHeaders {
    include 'lauxlib.h', 'lua.h', 'lua.hpp', 'luaconf.h', 'lualib.h'
    }
    }
    }

    }
    //创建一个luac执行文件构建入口
    luac(NativeExecutableSpec) {
    sources {
    c {
    source {
    srcDir "src/main/c/lua"
    include '*.c'
    exclude 'lua.c'
    }
    exportedHeaders {
    include 'lauxlib.h', 'lua.h', 'lua.hpp', 'luaconf.h', 'lualib.h'
    }
    }
    }
    }

    }

    }
  4. 最后 开始编译
    gradle刷新同步后, 我们在右侧gradle任务面板可以看到多出lua和luac相关的task, 此时我们执行build任务开始对lua源码进行编译:

    image-20220926164804018

    编译完成后, 我们可以在build文件中查看到生成的可执行文件:

    image-20220926165101437

    双击可正常运行:

    image-20220926165135047

    至此 我们的lua编译完毕

附加

  1. 如果你只想编译lua而不编译luac, 那么可以单独运行luaExecutable:

    image-20220926172451757

  1. 在gradle配置文件中的组件的名称可以自定义

    image-20220926172714010

关于编译工具

编译工具和构建工具是两个不同的东西:

  • C/C++/Object-C语言常用的编译工具有: GCC,Clang

  • Java语言的编译工具为Javac, 当然GCC也能编译java语言

  • Android的编译工具为aapt,so库的编译早期采用的是GCC, 现在是Clang

上面对于lua的编译, 由于我测试时使用的是Mac平台, 同时电脑还装了Xcode, 所以内部默认采用的编译器是clang

关于Clang和GCC的介绍, 可以参见之前的文章《xcode中三种编译器的区别》

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Linux 系统下使用 systemd 控制 frps 及配置开机自启

发表于 2022-09-22

操作

这个示例将会演示在 Linux 系统下使用 systemd 控制 frps 及配置开机自启。

在 Linux 系统下,使用systemd 可以方便地控制 frp 服务端 frps 的启动和停止、配置后台运行和开启自启。

要使用 systemd 来控制 frps,需要先安装 systemd,然后在 /etc/systemd/system 目录下创建一个 frps.service 文件。

  1. 如Linux服务端上没有安装 systemd,可以使用 yum 或 apt 等命令安装 systemd。

    1
    2
    3
    4
    # yum
    yum install systemd
    # apt
    apt install systemd
  2. 使用文本编辑器,如 vim 创建并编辑 frps.service 文件。

    1
    $ vim /etc/systemd/system/frps.service

    写入内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [Unit]
    # 服务名称,可自定义
    Description = frp server
    After = network.target syslog.target
    Wants = network.target

    [Service]
    Type = simple
    # 启动frps的命令,需修改为您的frps的安装路径
    ExecStart = /path/to/frps -c /path/to/frps.ini

    [Install]
    WantedBy = multi-user.target
  3. 使用 systemd 命令,管理 frps。

    1
    2
    3
    4
    5
    6
    7
    8
    # 启动frp
    systemctl start frps
    # 停止frp
    systemctl stop frps
    # 重启frp
    systemctl restart frps
    # 查看frp状态
    systemctl status frps
  4. 配置 frps 开机自启。

    1
    systemctl enable frps

本文转载自: gofrp文档

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

supervisor和systemd的对比

发表于 2022-09-21

前言

过去我们项目组的应用都是用 supervisord 托管的。最近因为某些因素,无法使用 supervisord,因此考虑改用 systemd。

systemd作为主流 Linux 发行版的默认选项,之前多多少少用过一点 systemd。不过这次需要上生产环境,所以抽空深入研究一番。

为什么要用supervisord?

  1. 实现进程的分组管理,比如支持一同启动/停止多个生产者/消费者实例。
  2. 进程崩溃的时候可以重启

要想改用 systemd,需要看下systemd 如何应对这两个问题。
(如无指明,在本文中,supervisord 的配置项在 [program:x] 下面,而 systemd 的配置项则位于 [Service])

进程控制

无论 supervisord 还是 systemd,都采用 ini作为配置文件的格式。跟 supervisord 不同的是,systemd 每个程序都要单独开一个unit文件。

supervisord 可以同时启动/停止配置文件中所有的进程(或者某个进程组配置中的进程)。systemd可以用依赖来实现这一点。下面例子中,我们
就创建了一个可以同时管理的进程组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
; group.target
[Unit]
Description=Application
Wants=prog1.service prog2.service
; prog1.service
[Unit]
Description=prog1
PartOf=group.target

[Service]
ExecStart=/usr/bin/prog1
Restart=on-failure
; prog2.service
[Unit]
Description=prog2
PartOf=group.target

[Service]
ExecStart=/usr/bin/prog2
Restart=on-failure

systemctl start group.target,prog1 和 prog2 也会带起来。systemctl restart group.target,prog1 和 prog2 也会跟着重启。

相对来说,supervisord 的做法更加直观一些。

如果要更改supervisord的配置文件,supervisord 需要运行 supervisorctl reread 才会生效。
而 systemd 则需要 systemctl daemon-reload。半斤八两吧。

不过 supervisord 有一个好。如果你不知道哪些程序的配置改变了,简单地执行 supervisorctl update,所有涉及的进程都会被重启。
而 systemd 貌似做不到这一点。

systemd 可以指定 stop 操作时可以选择的命令(ExecStop=)。另外它还提供了 ExecReload=,可以自定义调用 systemctl reload xxx 重新读取程序配置文件时的操作。
supervisord不支持 reload 指定进程。同时对于 stop操作,它只允许你选择要发送哪种信号…

supervisord 的 stopwaitsecs 可以控制stop 操作后等待程序退出的耐心(以秒衡量)。待给定的耐心都消耗完毕后,supervisord 才会痛下杀手,发送 SIGKILL。

systemd 对应的配置项是 TimeoutStopSec=。systemd 会给多一次机会,在下最后通牒之前,会先发送 SIGTERM,过另一个TimeoutStopSec之后才发送 SIGKILL。

进程重启

为了避免在supervisord 和 systemd两套术语间迷糊,请允许我抛弃所有术语,用自己的话描述。
life-cycle

从上图可以看到,进程在 RUNNING 之前,会有一个 STARTING 的过程。在 STARTING 过程中,进程可能会读取配置文件,进行初始化。
这一过程中的错误处理,跟 RUNNING 状态的应当有所不同。
以上是supervisord的想法。

所以supervisord 提供了单独的 startretries 配置项,用来配置 STARTING 阶段的重启次数。
systemd 对此没有特殊处理。

一个程序,从 RUNNING 到 EXITED,有两种可能:正常退出或异常退出…(废话)
这两种情况,是通过配置的退出码来区分的。对于 supervisord,这个配置项是 exitcodes。systemd 则通过 SuccessExitStatus 来控制。
有趣的是,exitcodes 的默认值是 0,2,不知道为何它会认为 2 也是正常的退出码。

如果配置了 autorestart = true,只要程序退出,supervisord 都会把它启动起来。相对的,如果配置的是 autorestart = unexpected,则只有
异常退出才会重启。这两个选项,在 systemd 里对应 Restart=always 和 Restart=on-failure。systemd 还提供了 Restart=on-success(只有正常
退出才重启)和 Restart=on-abort(只有收到异常信号才重启)。

对于重启次数,supervisord 没有作限定。因为重启一个程序时,supervisord 会先让它处于 STARTING 状态。这个状态的持续时间,是由配置项
中的 startsecs 决定的,默认 1 秒。如果是不可恢复的错误,程序就不可能成功进入到 RUNNING 状态。当然也许存在这样的情况,程序运行 1 秒
后,就会崩溃。那么它就会陷于不停重启的无间地狱。

systemd 对此一如既往,提供了 N 多选项以供采用。你可以用 RestartSec 控制每次重启的间隔,可以用 StartLimitInterval 和 StartLimitBurst 设定
给定周期内能够重启的次数。比如指定 StartLimitInterval=1s,StartLimitBurst=3,就可以实现跟 supervisord 一致的默认重启策略。

比较完最基本的两种功能,让我们继续看看,两者在一些小细节上的对对碰。

控制实例数

supervisord 可以用 numprocs 来控制单个程序对应的实例数。systemd 也可以做到这一点,虽然有点麻烦(某种意义上,更加强大)。
systemd 会把以 @ 结尾的 service 文件当作模板,在运行时根据给定的参数展开成多个实例。

具体实现方式见:http://0pointer.de/blog/proje…

日志

supervisord 能够重定向被托管的程序的 stdout 和 stderr 到日志文件中,并提供日志切割服务。systemd 也支持这一点,尽管它的实现有很大的不同。

根据鄙人的经验,基于定期检查的日志切割服务,不是个好的选择。
一旦遇上突发高峰,有可能会出现日志无法及时切割的情况;而调小检查间隔,大部分情况下都在无意义地空转。(说的就是你,logroated)
好在无论是 supervisord,还是systemd,提供的切割服务都是实时的。每当写入内容会超过上限时,就会自动切割。

systemd 的日志服务是通过 journald 组件实现的。你可以在 /etc/systemd/journald.conf 中配置它。
journald 默认的日志存储形式是 Storage=auto。这个选项比较奇妙,如果你创建了 /var/log/journal 文件夹,那么它就会把日志写到这个文件夹下。否则不进行持久化。

持久化后的日志是这个样子的:

1
2
3
4
/var/log/journal/c4010ceea79847afbedecb60a775db96/
├── system.journal
├── user-1000.journal
└── user-65534.journal

第一次看到这样的目录结构,说不定你会大吃一惊。journald 设计者脑洞不是一般的大。从这个结构上,根本看不出应用日志在哪里嘛。
不,完全没有这样的必要,因为所有的程序的日志都会写到一块去。不分彼此,全变成一团浆糊。随便一提,日志默认都是压缩的。

要看日志,你得用 journalctl。比如看 prog1.service 的日志,需要 journalctl -u prog1.service。要看特定时期的日志,需要 journalctl --since $timestamp --until $timestamp。

这么前卫的设计我可接受无能。这种 journalctl 控制一切的方式,导致 systemd 日志无法集成到传统的日志收集工具中。
程序员工具箱中各种 text base 处理工具,对此也大眼瞪小眼,只能对着 journalctl 低三下四,接受对方的小脾气。

journald 提供了三个配置项,RuntimeMaxFileSize= 和 RuntimeMaxFiles=。顾名思义,就是单个日志文件大小和允许的日志数。
另外,RuntimeMaxUse= 和 RuntimeKeepFree= 可以控制总大小的上限。

supervisord 在这方面做的要好得多。通过 stdout/stderr_logfile_maxbytes 和 stdout/stderr_logfile_backups,你可以规划每一个程序的日志文件的切割粒度。
不同程序的日志不会挤一起,产生日志少的程序也不会被产生日志多的程序干扰。

开机自启

systemd 支持开机自启, 而supervisor开机自启需依赖其他程序实现, 其本身也是被监控的对象

systemd vs supervisord

除了以上几点外,还有一些没有具体提到的功能。
比如 supervisord 通过 priority 配置进程启动顺序,以及 systemd 对应的 Before/After 依赖机制。
比如 supervisord 的 events 功能,和与之相对应的 systemd 的 notify 机制。
比如 supervisord 可以管理 fastcgi(真有人这么做吗)。
比如 systemd 提供的基于 cgroup 的资源限制。
由于没有使用经验,对这些功能就不作一一比较了。

总结

systemd和 supervisord 各有长短,不存在哪一方绝对的碾压。

systemd 跟Linux 紧密结合,所需的依赖少,其提供的保障自然比 supervisord 更可靠。然而在强大的能力背后,也有配置复杂、不易上手等问题。

supervisord偏于应用层,却因此有独特的用武之地。

举个例子,许多人会往 docker打包里面封入一份supervisord,让它来做 PID 1,以此稍微增强下健壮性。
换 systemd 做同样的事,就像用园艺剪刀裁纸,即使能够顺利完成,也难免事倍功半。毕竟这样的方式跟systemd 的设计是背道而驰的。

本文转载自: segmentfault

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

如何使用supervisor实现内网穿透持久化

发表于 2022-09-21

前言

使用内网穿透时 可能会出现各种不稳定因素导致服务中断, 一旦中断 那么外网就无法对内网进行访问了

为了保证连接的持久稳定性, 我们需要对进程进行监控, 一旦发现服务掉线或者出错 就自动重启程序

为了实现这个需求, 我们可以用supervisor, 它是由python写的一个进程管理工具, 主要功能有:

  • 启动、重启、关闭进程
  • 服务挂掉后,自动重启
  • 可执行文件或者配置文件修改后,服务自动重启
  • 内置可视化界面管理

上一章给大家介绍了《使用frp进行内网穿透实现外网访问局域网中的服务器》

由于服务端使用的是第三方的中转服务器, 服务器的稳定性暂不考虑, 目前只需关心客户端这一块, 这里 我以内网中Mac机器为例给大家介绍supervisor的使用

开始实现

  1. 安装supervisor

    1
    brew install supervisor

    或者

    1
    sudo pip3 install supervisor
  2. 检查是否安装成功

    1
    brew info supervisor

    或者

    1
    brew info supervisor

    显示版本号则说明安装成功

  3. 创建配置文件

    在/usr/local/etc/目录下创建一个配置文件名为supervisord.conf

    1
    touch supervisord.conf
  4. 配置服务

    在配置文件中添加以下内容

    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
    26
    27
    [inet_http_server]         ;开启http服务 
    port=127.0.0.1:9001 ;指定端口号为9001
    username=user ; 用户名
    password=123 ; 密码



    [supervisord]
    logfile=/tmp/supervisord.log ; 日志文件
    logfile_maxbytes=50MB ; 日志文件最大50Mb
    logfile_backups=10 ; 日志备份数量
    loglevel=info ; 打印日志的等级 默认为info 除此之外还有 debug,warn,trace
    pidfile=/tmp/supervisord.pid ;pid文件路径
    nodaemon=false ; 是否在前台运行
    silent=false ;是否关闭日志打印
    minfds=1024
    minprocs=200


    [supervisorctl]
    serverurl=http://127.0.0.1:9001 ;访问这个服务进行进程管理
    username=user ; 需要和http用户名保持一致
    password=123 ; 需要和http密码保持一致 用于管理工具的连接 如果不配置的话 每次使用supervisorctl都得手动输入用户名密码


    [rpcinterface:supervisor] ;这个配置必须要有
    supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

    配置详解:

    • [inet_http_server]: 开启http服务 提供可视化监控界面
    • [supervisord]:supervisor服务配置 缺少它supervisor无法启动
    • [supervisorctl]:supervisor管理工具
  1. 启动supervisor

    1
    supervisord -c /usr/local/etc/supervisord.conf

    启动后 我们在浏览器中输入http://127.0.0.1:9001, 填入配置文件中的username和password, 进入到守护进程管理页面

    image-20220921152026301

    我们在页面中为发现进程信息, 因为还没有配置需要进行守护的进程

  2. 添加需要进行监测并守护的进程

    在配置文件中追加以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [program:frpc] ;名称为frpc  这个可以自定义 但是不能重复
    command=/Users/songjian/frp/frpc/frpc -c ./frpc.ini ; 需要运行的程序指令
    directory=/Users/songjian/frp/frpc ;程序目录
    autostart=true ; supervisor 启动时跟随启动
    autorestart=true ; 程序崩溃时自动重启
    startsecs=5 ; # of secs prog must stay up to be running (def. 1)
    startretries=3 ;重试次数
    stdout_logfile=/Users/songjian/frp/frpc/supervisord.log ; 日志文件路径
    stdout_logfile_maxbytes=20MB ; 日志文件最大容量
    stdout_logfile_backups=10 ; # 日志备份数量
  3. 重载配置文件

    1
    supervisorctl

    执行后提示需要验证 输入用户名和密码后进入子命令窗口, 然后输入reload进行重载:

    image-20220921172100244

    此时我们刷新浏览器可以看到守护的程序已经启动:

    image-20220921173043546

    我们可以直接在浏览其中直接对其进行重启 停止 以及日志查看等操作

    至此 我们supervisor对frpc的守护已初步实现

supervisor开机自启

我们希望内网机器开机后自动启动supervisor, 在Mac平台实现很简单, 只需执行以下指令即可:

1
brew services start supervisor

brew services内部使用的是launchctl, 简化了launchctl的繁琐操作, brew services的常用命令有:

1
2
3
4
5
6
brew services list  # 查看使用brew安装的服务列表
brew services run formula|--all # 启动服务(仅启动不注册)
brew services start formula|--all # 启动服务,并注册
brew services stop formula|--all # 停止服务,并取消注册
brew services restart formula|--all # 重启服务,并注册
brew services cleanup # 清除已卸载应用的无用的配置

supervisorctl管理工具提供的功能

我们可以利用supervisorctl对我们的守护进行进行启动 停止 重启等操作, 具体的可以输入help进行查看:

image-20220921172300446

  1. 停止 supervisor

    1
    shutdown

    该指令不仅会停止 supervisor, 还会停止其守护的所有程序

  2. 停止某个守护进程

    1
    stop 进程名
  3. 停止所有守护进程

    1
    stop all
  4. 重启某个守护进程

    1
    restart 进程名
  5. 重载整个配置文件

    1
    reload

    所有子进程会重启

  6. 更新配置文件

    1
    update

    配置文件中有改动的进程会被重启 没有改动的不受影响

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用frp进行内网穿透实现外网访问局域网中的服务器

发表于 2022-09-20

前言

之前给大家介绍过使用内网云实现内网穿透的方案, 一行指令搞定, 详见《使用内网云进行内网穿透实现外网访问局域网中的服务器》

今天给大家介绍如何使用frp实现内网穿透

frp是一个免费开源的内网穿透工具, 包含服务端(frps)和客户端( frpc)

Github

假如你自己有云服务器, 那么将服务端安装到具有公网ip的服务器中, 将客户端安装到内网的机器上, 即可实现内网穿透功能

当然 如果你没有云服务也没有关系 网上有些热心肠的大佬们给我们提供了中转服务器 比如: freefrp:

image-20220920172928529

而我们要做的仅仅就是在内网的机器上安装用于连接的客户端即可

接下来我以本地的Mac电脑为例 充当内网机器 介绍使用方法

使用方法

http穿透

  1. 首先下载客户端程序

    点击下载

    image-20220920173201984

    由于是Mac系统 因此我们选择Darwin_amd64, 下载后解压:

    image-20220920174602538

    客户端只用frpc开头的文件, 其他的可以移除,

  2. 修改配置文件

    打开配置文件frpc.ini, 然后修改成以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [common]
    server_addr = frp.freefrp.net
    server_port = 7000
    token = freefrp.net

    [mac_http]
    type = http
    local_ip = 127.0.0.1
    local_port = 13000
    custom_domains = git.newban.cn

    image-20220921101048772

    参数详解:

    • 中括号中的名称可以自定义 但不能重复

    • type: 表示连接类型, 支持http/https udp tcp 等协议

    • server_addr:服务器 IP 地址或者域名地址

    • *server_port *:服务端口号

    • token:服务端访问密码

    • local_ip: 需要进行穿透的内网ip, 通常为127.0.0.1 如果使用虚拟机或者docker 建议改成局域网ip

    • local_port: 需要进行穿透的内网端口号

    • custom_domains: 自定义域名 需要将域名解析到服务器地址 这样使用域名就能直接访问到内网程序了

  1. 域名解析

    将配置文件中的自定义域名以CNAME的方式解析到frp.freefrp.net

  2. 启动frpc客户端程序

    1
    ./frpc
  3. 浏览器访问

    此时 我们通过域名就能直接在任意浏览器上访问到127.0.0.1:3000

  4. 多域名解析

    假如我们需要将多个不同域名同时解析到同一个内网程序, 那么只需增加一个新模块, 配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    [common]
    server_addr = frp.freefrp.net
    server_port = 7000
    token = freefrp.net

    [mac_http]
    type = http
    local_ip = 127.0.0.1
    local_port = 13000
    custom_domains = git.newban.cn


    [mac_http2]
    type = http
    local_ip = 127.0.0.1
    local_port = 13000
    custom_domains = git.insoan.com
  1. 实现以Web的形式可视化配置客户端

    只需在common的节点下配置admin参数即可, 如下:

    1
    2
    3
    4
    5
    6
    7
    8
    [common]
    server_addr = frp.freefrp.net
    server_port = 7000
    token = freefrp.net
    admin_addr = 127.0.0.1 #客户端Web管理地址
    admin_port = 7122 #客户端Web管理端口
    admin_user = admin #客户端Web管理用户名
    admin_pwd = 123456 #客户端Web管理密码

    配置完后重启frp, 然后在浏览器输入http://127.0.0.1:7122, 即可以Web的形式监控当前正在穿透的程序:

    image-20220922115156138

ssh穿透

  1. 配置TCP连接

    如果我们需要进行ssh访问, 那么我们需要在客户端配置tcp协议, 配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    [common]
    server_addr = frp.freefrp.net
    server_port = 7000
    token = freefrp.net

    [mac_http]
    type = http
    local_ip = 127.0.0.1
    local_port = 13000
    custom_domains = git.newban.cn

    [mac_ssh]
    type = tcp
    local_ip = 127.0.0.1
    local_port = 22
    remote_port = 12323

    参数解析:

    • remote_port: 服务器端口映射 意思就是将服务器的12323端口映射到内网的22端口
  2. ssh访问

    此时 我们在命令窗口执行以下指令就可以进行ssh连接了

    1
    ssh -p 12323 root@frp.freefrp.net

    由于我们之前将自定义域名以CNAME形式解析到了frp.freefrp.net, 所以 我们也可以用自定义域名进行连接, 如下:

    1
    ssh -p 12323 root@git.newban.cn

总结

至此 我们的内网穿透客户端配置就ok了, 相比内网云 使用frpc+freefrp.net中转服务器的模式进行内网穿透可以实现完全免费且稳定的服务

下一章 给大家介绍《如何使用supervisor实现内网穿透持久化》

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用内网云进行内网穿透实现外网访问局域网中的服务器

发表于 2022-09-20

前言

有时候我可能会借助家里的电脑临时充当服务器供外网访问, 此时需要进行内网穿透才能实现

网上偶然发现一个提供内网穿透服务的网站, 名为内网云:

image-20220920162143938

如果是临时使用 那么完全免费, 付费的话5块钱一个月

接下来给大家介绍 如何使用

使用指南

http映射

假设我的电脑上开了一个Web服务, 地址为:http://localhost:3000, 我们想实现外网访问到这个地址的内容, 此时我们可以在电脑的命令窗口中输入以下指令:

1
ssh -R 80:127.0.0.1:3000 sh@sh3.neiwangyun.net

指令解析:

  • ssh:ssh远程命令
  • -R:远程端口绑定
  • 80:固定端口
  • 127.0.0.1:固定的本机网络
  • 3000:你需要转发的网络端口,自行更改
  • sh:默认匿名账号,不需要密码验证
  • sh3.neiwangyun.net:内网云服务器节点的地址,固定值

简而言之 这句指令的意思就是将sh3.neiwangyun.net服务器的80端口转发到本地的3000

执行完毕后出现以下内容:

image-20220920162759901

结果解析:

  • username:sh账号名称
  • type:anonymous账号类型
  • subdomain: xxxxxxxxxx.neiwangyun.net 子域名
  • bandwidth: random 网络带宽
  • expire_time: random过期时间
  • unid: 唯一识别码
  • http:http链接
  • https:https链接
  • ipport:直连用的ip和端口
  • remote_ip:客户端ip,服务器看到的连接者IP

此时 我们在浏览器中输入http/https的地址则可以访问到http://localhost:3000的内容

ssh映射

假如我们需要在外网中对家里的电脑进行ssh连接, 那么我们需要更改指令端口,如下:

1
ssh -R 80:127.0.0.1:22 sh@sh3.neiwangyun.net

image-20220920164300687

执行完毕后 我们需要用ipport的值进行ssh访问, 如下:

1
ssh hostname@olveddnzffdhshsh3.neiwangyun.net:31258

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

本地nginx反向代理localhost端口转发失败的解决方案

发表于 2022-09-20

问题

有时候为了方便 懒得开虚拟机直接将nginx部署在了本地, 在进行端口映射测试时可能会出现访问502 Bad Getway的问题

我们先来分析一下nginx的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
http{

upstream gitea{
server 127.0.0.1:13000;
}
server{
listen 80;
server_name localhost;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://gitea;
break;
}
}

}

这里我们将127.0.0.1:13000映射给了localhost:80, 如果我们在浏览器中输入localhost显然是无法访问的

解决方案

如果想要正常访问 需要将127.0.0.1改成局域网ip地址, 修改后的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
http{

upstream gitea{
server 192.168.13.155:13000;
}
server{
listen 80;
server_name localhost;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://gitea;
break;
}
}

}

重启nginx使配置生效, 此时即可正常转发访问了

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

关于使用ssh进行仓库clone端口号非22的解决办法

发表于 2022-09-19

问题

我们在使用docker搭建私有git仓库时, 会将容器的22端口映射到宿主的其他端口上, 此时如果我们使用ssh地址进行仓库clone, 则会报错 提示ssh: connect to host localhost port 22: Connection refused:

image-20220920121534132

假设映射到宿主的端口号为10022, 那么解决方案如下:

解决方案

  1. 第一种 clone时指定端口号:

    1
    git clone ssh://git@localhost:10022/songjian/ggg.git

    注意: 需要带上ssh://这个协议头

  2. 第二种 在.ssh目录下的config文件中增加port字段指定端口访问:

    1
    2
    3
    4
    5
    Host localhost
    HostName localhost
    Port 10022
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_rsa

    由于git默认port是22, 此时我们修改后则可以按照正常的形式进行仓库的克隆:

    1
    git clone git@localhost/songjian/ggg.git
  3. 第三种 使用nginx反向代理

    在nginx.conf文件中配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    stream {
    upstream ssh-proxy {
    server 服务器ip:10022;
    }
    server {
    listen 22;
    proxy_pass ssh-proxy;
    }
    }

    配置好后, 直接正常形式clone:

    1
    git clone git@localhost/songjian/ggg.git

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用Docker搭建基于gitea的私有git仓库

发表于 2022-09-19

前言

最近打算将一些私有仓库转移到自己服务器上, 以备不时之需, 目前免费开源的Git仓库框架有Gitlab和Gitea, 考虑到资源消耗问题, 果断选择了Gitea

Gitea的Github地址

接下来分享我个人使用Docker快速搭建Gitea的过程

步骤如下

安装gitea

  1. 搜索gitea镜像

    1
    docker search gitea
  2. 拉取gitea镜像

    1
    docker pull gitea/gitea
  3. 创建并运行容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    docker run -id \
    --privileged=true \
    --restart=always \
    --name=c_gitea \
    -p 10022:22 \
    -p 13000:3000 \
    -v /root/app/gitea:/data \
    -h c_gitea \
    gitea/gitea:latest

    参数详解:

    • privileged: 是否授予容器root权限
    • restart : docker启动是是否自动启动容器
    • name: 表示容器别名
    • -p 10022:22: 容器暴露了22和3000端口
    • -v /root/app/gitea:/data: 容器的data目录挂载到/root/app/gitea
  4. 浏览器访问gitea配置页面

    1
    http://服务器ip:13000

    image-20220919172350179

    这里主要需要配置数据库以及域名 其他的保持默认即可

    首先数据库的话 这里有多种数据库可选, 考虑到资源消耗和移植方便 我选择sqlite3

    那么在进行配置之前 我们需要先安装sqlite3来创建数据库文件

    依然使用docker快速安装:

安装sqlite3

  1. 拉取镜像

    1
    docker pull nouchka/sqlite3
  2. 创建并运行容器

    1
    2
    3
    4
    5
    6
    7
    docker run -id \
    --restart=always \
    --name=c_sqlite \
    -p 1433:1433 \
    -v /root/app/gitea/sqlite:/root/db \
    -h c_sqlite \
    nouchka/sqlite3:latest
  3. 进入容器

    1
    docker exec -it c_sqlite bash
  1. 进入容器后运行指令创建数据库

    1
    sqlite3 数据库名.db

    运行创建数据库指令时 sqlite3默认会在当前目录生成db文件, 所以执行前要确保当前目录为挂载目录,也就是/root/db

    image-20220919182016029

    执行`sqlite3`进入`SQL`状态, 此时我们输入`.database`可以查看并刷新已经创建的数据库文件 这一步关键 否则宿主挂载目录文件不更新
  2. 退出数据库

    1
    .quit

    image-20220919182305343

    此时我们在宿主的`/root/app/gitea/sqlite`可以查看到刚刚生成的数据库

数据库关联

我们需要明白的是, 在docker中gitea容器是个独立的系统, 在配置页面中填写的路径皆为gitea容器内部路径, 而非宿主路径

由于gitea容器的/data目录映射到了宿主的/root/app/gitea目录, 因此 我们需要将生成的sqlite数据库文件放置在宿主的/root/app/gitea目录下, 这样gitea容器才能访问到数据库文件

这一点 我在sqlite容器创建时已经考虑到了, 所以将sqlite挂载目录设为了/root/app/gitea/sqlite, 从而免去了数据库文件的迁移

此时 我只需在配置页面数据库路径一项填入/data/sqlite/gitea.db即可:

image-20220920101539648

如果后期需要修改配置可以进入/root/app/gitea/gitea/conf/app.ini 进行修改, 每次修改后记得需要重启gitea容器才能生效

配置完毕后 点击安装

紧接着自动跳转到登录页面, 此时我们注册一个新账号然后登录:

image-20220920102423120

至此 我们的私有仓库就搭建完毕了, 如果需要节省资源, 可以将sqlite容器停止, 它的存在只是为了创建数据库 以及必要的时候进行数据自定义处理, 暂时不需要它保持运行状态

外部仓库同步

gitea支持从外部仓库导入 支持以下常见厂商:

image-20220920103201263

如果从github 导入 首先需要去github中申请一个access token

image-20220920104007824

当然我们也可以直接使用clone的形式进行迁移 无需token:

image-20220920115211964

后面的就不多介绍了

自定义域名

正常情况下我们可以通过地址http://服务器公网IP:13000来访问服务器, 如果需要配置自定义域名, 那么需要修改一些配置:

首先域名端, 也就是域名解析需要指向服务器IP, 这点不做过多介绍 大家都明白

另外就是服务端

由于我使用了Nginx进行反向代理, 并且给docker配置了桥接网络, 所以在nginx.conf文件中配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
http{
upstream gitea{
server c_gitea:3000;
}
server{
listen 80;
server_name git.newban.cn;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://gitea;
break;
}
}

}

通过桥接网络 我们可以直接使用容器别名实现容器间的相互通信, 减少端口暴露的风险

gitea目录结构

数据库主要用于存放用户和仓库相关的配置数据

image-20220920112051764

而我们的代码主要是放在了本地磁盘的/root/app/gitea/git目录下:

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
26
27
28
29
.
├── git
│   ├── lfs
│   └── repositories
├── gitea
│   ├── attachments
│   ├── avatars
│   ├── conf
│   ├── home
│   ├── indexers
│   ├── jwt
│   ├── log
│   ├── packages
│   ├── queues
│   ├── repo-archive
│   ├── repo-avatars
│   ├── sessions
│   └── tmp
├── sqlite
│   └── gitea.db
└── ssh
├── ssh_host_dsa_key
├── ssh_host_dsa_key.pub
├── ssh_host_ecdsa_key
├── ssh_host_ecdsa_key.pub
├── ssh_host_ed25519_key
├── ssh_host_ed25519_key.pub
├── ssh_host_rsa_key
└── ssh_host_rsa_key.pub

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

123…39

乱码三千

android程序员一枚,擅长java,kotlin,python,金融投资,欢迎交流~

387 日志
120 标签
RSS
© 2022 乱码三千
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%