ursachec / CPAProxy

A thin Objective-C wrapper around Tor.
Other
161 stars 49 forks source link

Works in an emulator but not on a device #61

Open MozaTora opened 7 years ago

MozaTora commented 7 years ago

I tried to send a GET request to https://facebookcorewww.onion. In an emulator everything works perfectly, I receive a web page but on a real device I have an error and the data buffer is nil. I'm not sure where to move next.

iOS version 10.2.1 Xcode version 8.2.1

Some extracts from the log file

...

02:59:57 test(libsystem_network.dylib)[362] <Debug>: -[NWConcrete_nw_endpoint_resolver startWithHandler:] [2.1 127.0.0.1:60223 waiting resolver (unsatisfied)]
02:59:57 mDNSResponder[93] <Info>:  16: connect_callback: Adding FD for uid 501
02:59:57 test(libsystem_network.dylib)[362] <Debug>: nw_endpoint_proxy_receive_report [2 facebookcorewwwi.onion:443 in_progress proxy (unsatisfied)] received child report:[2.1 127.0.0.1:60223 in_progress resolver (unsatisfied)]
02:59:57 mDNSResponder[93] <Info>:  16: DNSServiceCreateConnection START PID[362](test)
02:59:57 test(libsystem_network.dylib)[362] <Info>: nw_connection_endpoint_report [2.1 127.0.0.1:60223 in_progress resolver (unsatisfied)] reported event resolver:start_dns
02:59:57 mDNSResponder[93] <Info>:  16: DNSServiceCreateConnection STOP PID[362](test)
02:59:57 mDNSResponder[93] <Info>:  16: Removing FD

02:59:57 test(libsystem_dnssd.dylib)[362] <Notice>: dnssd_clientstub DNSServiceRefSockFD called with NULL DNSServiceRef
02:59:57 test(libsystem_network.dylib)[362] <Error>: nw_resolver_create_dns_service_on_queue DNSServiceSetDispatchQueue failed: BadParam(-65540)

...

02:59:57 test(libsystem_network.dylib)[362] <Debug>: __tcp_connection_start_block_invoke 2 sending event TCP_CONNECTION_EVENT_DISCONNECTED in response to state failed and error Error Domain=kNWErrorDomainPOSIX Code=50 "Network is down" UserInfo={NSDescription=Network is down}

...

03:01:44 test[362] <Notice>: error = Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={NSErrorFailingURLStringKey=https://facebookcorewwwi.onion/, _kCFStreamErrorCodeKey=50, NSErrorFailingURLKey=https://facebookcorewwwi.onion/, NSLocalizedDescription=The Internet connection appears to be offline., _kCFStreamErrorDomainKey=1, NSUnderlyingError=0x168bd560 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=50}}}

The source code. Basically it's just a copy of the example

#include <CPAProxy/CPAProxy.h>

@interface ViewController ()
@property (nonatomic, strong, readwrite) CPAProxyManager *cpaProxyManager;
@end

@implementation ViewController

- (void)handleCPAProxySetupWithSOCKSHost:(NSString *)SOCKSHost SOCKSPort:(NSUInteger)SOCKSPort
{
    // Create a NSURLSessionConfiguration that uses the newly setup SOCKS proxy
    NSDictionary *proxyDict = @{
                                (NSString *)kCFStreamPropertySOCKSProxyHost : SOCKSHost,
                                (NSString *)kCFStreamPropertySOCKSProxyPort : @(SOCKSPort)
                                };
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
    configuration.connectionProxyDictionary = proxyDict;

    NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    NSURL *URL = [NSURL URLWithString:@"https://facebookcorewwwi.onion/"];
    NSURLSessionDataTask *dataTask = [urlSession dataTaskWithURL:URL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (data) {
            NSString* data_str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"%@", data_str);
        } else {
            NSLog(@"error = %@", error);
        }
    }];

    [dataTask resume];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL *cpaProxyBundleURL = [[NSBundle bundleForClass:[CPAProxyManager class]] URLForResource:@"CPAProxy" withExtension:@"bundle"];
    NSBundle *cpaProxyBundle = [NSBundle bundleWithURL:cpaProxyBundleURL];
    NSString *torrcPath = [cpaProxyBundle pathForResource:@"torrc" ofType:nil];
    NSString *geoipPath = [cpaProxyBundle pathForResource:@"geoip" ofType:nil];

    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSString *torDataDir = [documentsDirectory stringByAppendingPathComponent:@"tor"];

    CPAConfiguration *configuration = [CPAConfiguration configurationWithTorrcPath:torrcPath geoipPath:geoipPath torDataDirectoryPath:torDataDir];
    _cpaProxyManager = [CPAProxyManager proxyWithConfiguration:configuration];

    [_cpaProxyManager setupWithCompletion:^(NSString *socksHost, NSUInteger socksPort, NSError *error) {
        if (error == nil) {
            NSLog(@"Connected: host=%@, port=%lu", socksHost, (long)socksPort);
            [self handleCPAProxySetupWithSOCKSHost:socksHost SOCKSPort:socksPort];
        }
    } progress:^(NSInteger progress, NSString *summaryString) {
        NSLog(@"%li %@", (long)progress, summaryString);
    }];
}

@end
rainwolf commented 7 years ago

It does seem to work partly on device, you can still connect to non-onion hosts (like https://check.torproject.org) that way on device. For onion hosts NSURLProtocol seems to complain that it's an unsupported URL, subclassing NSURLProtocol might work but I can't be certain (I couldn't get it to work).

I can still connect to onion addresses (not http servers) on my device, so there is probably an arduous workaround for you. OnionBrowser may offer clues on how to get there.

Fonta1n3 commented 5 years ago

I am having the exact same issue in iCepa Tor.framework... Very very frustrating. What is the point of using Tor if you can not connect to hidden services? I would be very keen to know if you solved this? I am sure Onion Browser has a work around but I only know Swift. I am making an open source Bitcoin app that allows you to connect to and control your own full node. I am able to connect to the nodes V3 hidden service in simulator but not on device and it is driving me crazy to be so close to such a great break through for iOS. If anyone can nudge me in the right direction I would really appreciate it.