ShadowCoel 分析之2: APP 中的依赖结构分析

本文最后更新于 2021年4月4日 晚上

上一篇分析文章中已经罗列了工程中的所有依赖库的作用, 这篇文章的重点就是看 APP 中这些依赖库的结构.

在 Xcode 中可以看到 ShadowCoel Project 中有如下图所示的 Target 列表:

下面就分别来看这些 Target 及其作用.

ShadowCoel Target

ShadowCoel: APP Target, 即 iOS APP 的实现.

在 APP Target 中 Embedded Binaries 如下图所示:

在 APP Target 中 Linked Framework and Libraries 如下图所示:

PacketTunnel Target

PacketTunnel: 可执行的 APP Extension. 它的主要作用就是和 Network Extension framework 进行交互.

其中依赖如下所示:

可以在这个 Target 的 info.plist 中找到相关的配置:

NSExtensionPrincipalClass: 即实现 APP Extension 的主视图的类名称, 这里的值是 PacketTunnelProvider.

NSExtensionPointIdentifier: 这里的值是 com.apple.networkextension.packet-tunnel, 表示的是这个 APP Extension 是一个 Packet Tunnel Provider Extension, 这样它就可以对诸如系统的 HTTP 代理等进行配置, 详见苹果官方文档.

关于 APP Extension 的更多信息详见苹果 APP Extension 的官方文档.

PacketTunnelProvider

声明如下所示:

1
2
3
4
5
@import NetworkExtension;

@interface PacketTunnelProvider : NEPacketTunnelProvider

@end

功能的实现主要是重写父类的如下方法:

1
2
3
4
5
6
7
8
// Start the network tunnel.
startTunnel(options:completionHandler:)

// Stop the network tunnel.
stopTunnel(with:completionHandler:)

// Stop the network tunnel from the Packet Tunnel Provider.
cancelTunnelWithError(_:)

之后会专门开一个文章对这个 Extension 的实现进行专门分析.

TodayWidget

可执行的 APP Extension, 在它的 info.plist 中有如下配置:

NSExtensionPointIdentifier 键的值是 com.apple.widget-extension, 表明这个 Extension 是一个 Today Extension, 如下表所示:

通过这个 APP Extension, 就具备了在 Today 中显示相关 Widget 视图的能力.

ShadowCoelLibrary

这个 Target 的主要功能是提供和代理功能相关的一些辅助功能. 之后会专门进行分析.

PacketProcessor

数据包处理器, 里面依赖了一个 tun2socks-iOS.

PacketProcessor 提供了如下接口:

1
2
3
4
5
6
7
8
9
10
11
12
#define TunnelMTU 1600
#define kTun2SocksStoppedNotification @"kTun2SocksStoppedNotification"

@interface TunnelInterface : NSObject
+ (TunnelInterface *) sharedInterface;
- (instancetype) init NS_UNAVAILABLE;
- (NSError *) setupWithPacketTunnelFlow:(NEPacketTunnelFlow *)packetFlow;
- (void) processPackets;
- (void) writePacket:(NSData *)packet;
- (void) startTun2Socks:(int)socksServerPort;
- (void) stop;
@end

之后会专门进行分析.

ShadowCoelModel

在其中建立了 APP 中的核心数据结构, 比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public enum ProxyType: String {
case Shadowsocks = "Shadowsocks"
case ShadowsocksR = "ShadowsocksR"
case V2ray = "V2ray"
case Trojan = "Trojan"
case GfwPress = "GFW.Press"
case Http = "HTTP"
case Https = "HTTPS"
case Http2 = "HTTP2"
case SSH = "SSH"
case Socks4 = "Socks4"
case Socks4a = "Socks4a"
case Socks5 = "Socks5"
case Socks5OverTls = "Socks5OverTLS"
case Sni = "SNI"
case Quic = "QUIC"
case None = "None"
}

详细的内容之后再分析.

ShadowCoelBase

提供其他辅助功能:

1
2
3
4
5
6
#import "ShadowCoel.h"
#import "JSONUtils.h"
#import "NSError+Helper.h"
#import "Settings.h"
#import "InfoInternal.h"
#import "NSString+Localize.h"

比如 ShadowCoel 类提供的功能如下:

1
2
3
4
5
6
7
8
9
10
11
12
@interface ShadowCoel : NSObject
+ (NSString * _Nonnull)sharedGroupIdentifier;
+ (NSURL * _Nonnull)sharedUrl;
+ (NSURL * _Nonnull)sharedDatabaseUrl;
+ (NSUserDefaults * _Nonnull)sharedUserDefaults;

+ (NSURL * _Nonnull)sharedGeneralConfUrl;
+ (NSURL * _Nonnull)sharedSocksConfUrl;
+ (NSURL * _Nonnull)sharedProxyConfUrl;
+ (NSURL * _Nonnull)sharedHttpProxyConfUrl;
+ (NSURL * _Nonnull)sharedLogUrl;
@end

详细的内容之后再分析.

阶段性总结

从上面两篇文章的分析, 可以看到, APP target 仅提供一个设置入口, 实际的代理配置主要通过 PacketTunnel 这个 APP Extension 来完成. 在其中启动 ss-local. 并通过进程间消息传递和 APP target, Today Extension 进行通信.

从下一篇文章开始, 将会介绍整个模仿实现的过程(开始会介绍整体需求获取和分析的过程).


ShadowCoel 分析之2: APP 中的依赖结构分析
https://blog.rayy.top/2019/09/14/2019-2019-09-14-shadowcoel1/
作者
貘鸣
发布于
2019年9月14日
许可协议