forked from SelfControlApp/selfcontrol
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPacketFilter.m
More file actions
180 lines (146 loc) · 6.13 KB
/
PacketFilter.m
File metadata and controls
180 lines (146 loc) · 6.13 KB
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//
// PacketFilter.m
// SelfControl
//
// Created by Charles Stigler on 6/29/14.
//
//
#import "PacketFilter.h"
NSString* const kPfctlExecutablePath = @"/sbin/pfctl";
@implementation PacketFilter
- (PacketFilter*)initAsWhitelist: (BOOL)whitelist {
if (self = [super init]) {
isWhitelist = whitelist;
rules = [NSMutableString stringWithCapacity: 1000];
}
return self;
}
- (void)addBlockHeader:(NSMutableString*)configText {
[configText appendString: @"# Options\n"
"set block-policy drop\n"
"set fingerprints \"/etc/pf.os\"\n"
"set ruleset-optimization basic\n"
"set skip on lo0\n"
"\n"
"#\n"
"# org.eyebeam ruleset for SelfControl blocks\n"
"#\n"];
if (isWhitelist) {
[configText appendString: @"deny out proto tcp from any to any\n"
"deny out proto udp from any to any\n"
"\n"];
}
}
- (void)addWhitelistFooter:(NSMutableString*)configText {
[configText appendString: @"pass out proto tcp from any to any port 53\n"];
[configText appendString: @"pass out proto udp from any to any port 53\n"];
[configText appendString: @"pass out proto udp from any to any port 123\n"];
[configText appendString: @"pass out proto udp from any to any port 67\n"];
[configText appendString: @"pass out proto tcp from any to any port 67\n"];
[configText appendString: @"pass out proto udp from any to any port 68\n"];
[configText appendString: @"pass out proto tcp from any to any port 68\n"];
}
- (void)addRuleWithIP:(NSString*)ip port:(int)port maskLen:(int)maskLen {
NSMutableString* rule = [NSMutableString stringWithString: @"from any to "];
if (ip) {
[rule appendString: ip];
} else {
[rule appendString: @"any"];
}
if (maskLen) {
[rule appendString: [NSString stringWithFormat: @"/%d", maskLen]];
}
if (maskLen) {
[rule appendString: [NSString stringWithFormat: @" port %d", port]];
}
if (isWhitelist) {
[rules appendString: [NSString stringWithFormat: @"pass out proto tcp %@\n", rule]];
[rules appendString: [NSString stringWithFormat: @"pass out proto udp %@\n", rule]];
} else {
[rules appendString: [NSString stringWithFormat: @"block out proto tcp %@\n", rule]];
[rules appendString: [NSString stringWithFormat: @"block out proto udp %@\n", rule]];
}
}
- (void)writeConfigurationWithToken:(NSString*)token {
NSMutableString* filterConfiguration = [NSMutableString stringWithCapacity: 1000];
if (token) {
[filterConfiguration appendString: [NSString stringWithFormat: @"# %@\n", token]];
}
[self addBlockHeader: filterConfiguration];
NSLog(@"Rules: %@", rules);
[filterConfiguration appendString: rules];
if (isWhitelist) {
[self addWhitelistFooter: filterConfiguration];
}
[filterConfiguration writeToFile: @"/etc/pf.anchors/org.eyebeam" atomically: true encoding: NSUTF8StringEncoding error: nil];
}
- (int)startBlock {
[self addSelfControlConfig];
[self writeConfigurationWithToken: nil];
NSArray* args = [@"-E -f /etc/pf.conf" componentsSeparatedByString: @" "];
NSTask* task = [[[NSTask alloc] init] autorelease];
[task setLaunchPath: kPfctlExecutablePath];
[task setArguments: args];
NSPipe* inPipe = [[[NSPipe alloc] init] autorelease];
NSFileHandle* readHandle = [inPipe fileHandleForReading];
[task setStandardOutput: inPipe];
[task launch];
NSString* pfctlOutput = [[NSString alloc] initWithData: [readHandle readDataToEndOfFile] encoding: NSUTF8StringEncoding];
[readHandle closeFile];
[task waitUntilExit];
NSArray* lines = [pfctlOutput componentsSeparatedByString: @"\n"];
for (NSString* line in lines) {
if ([line hasPrefix: @"Token: "]) {
[self writeConfigurationWithToken: line];
break;
}
}
return [task terminationStatus];
}
- (int)stopBlock:(BOOL)force {
NSString* currentConfig = [NSString stringWithContentsOfFile: @"/etc/pf.conf" encoding: NSUTF8StringEncoding error: nil];
NSString* token;
NSArray* lines = [currentConfig componentsSeparatedByString: @"\n"];
for (NSString* line in lines) {
if ([line hasPrefix: @"# Token :"]) {
token = [line substringFromIndex: [@"# Token : " length]];
break;
}
}
[@"" writeToFile: @"/etc/pf.anchors/org.eyebeam" atomically: true encoding: NSUTF8StringEncoding error: nil];
NSString* mainConf = [NSString stringWithContentsOfFile: @"/etc/pf.conf" encoding: NSUTF8StringEncoding error: nil];
lines = [mainConf componentsSeparatedByString: @"\n"];
NSMutableString* newConf = [NSMutableString stringWithCapacity: [mainConf length]];
for (NSString* line in lines) {
if ([line rangeOfString: @"org.eyebeam"].location == NSNotFound) {
[newConf appendFormat: @"%@\n", line];
}
}
newConf = [[newConf stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]] mutableCopy];
[newConf appendString: @"\n"];
[newConf writeToFile: @"/etc/pf.conf" atomically: true encoding: NSUTF8StringEncoding error: nil];
NSArray* args;
if (token && !force) {
args = [@"-X \(token) -f /etc/pf.conf" componentsSeparatedByString: @" "];
} else {
NSLog(@"Couldn't find pf token or using force, disabling with -d");
args = [@"-d -f /etc/pf.conf" componentsSeparatedByString: @" "];
}
NSTask* task = [NSTask launchedTaskWithLaunchPath: kPfctlExecutablePath arguments: args];
[task waitUntilExit];
return [task terminationStatus];
}
- (void)addSelfControlConfig {
NSMutableString* pfConf = [NSMutableString stringWithContentsOfFile: @"/etc/pf.conf" encoding: NSUTF8StringEncoding error: nil];
if ([pfConf rangeOfString: @"/etc/pf.anchors/org.eyebeam"].location == NSNotFound) {
[pfConf appendString: @"\n"
"anchor \"org.eyebeam\"\n"
"load anchor \"org.eyebeam\" from \"/etc/pf.anchors/org.eyebeam\"\n"];
}
[pfConf writeToFile: @"/etc/pf.conf" atomically: true encoding: NSUTF8StringEncoding error: nil];
}
- (BOOL)containsSelfControlBlock {
NSString* mainConf = [NSString stringWithContentsOfFile: @"/etc/pf.conf" encoding: NSUTF8StringEncoding error: nil];
return [mainConf rangeOfString: @"org.eyebeam"].location != NSNotFound;
}
@end