1

I am using a *jailbroken device and I want to write an application to list the open ports (e.g. TCP ports).

I have two ideas:

  • Use some native API to get list of opened ports
  • execute shell command to get a list of opened ports and parse the result of this shell command.

Which API or shell command should I use and how can I trigger it programmatically?

frankish
  • 6,738
  • 9
  • 49
  • 100
  • I would recommend to rephrase your question. I read it first time and made assumption that you just want to get list of open ports in shell (which implies that it's not software development question). And only on second reading I noticed part "make an application". And it looks like there were at least 4 persons who did the same. – Victor Ronin Sep 11 '13 at 13:35
  • @frankish: I voted to reopen and upvoted. I believe your question both legitimate and interesting. – Victor Ronin Sep 11 '13 at 23:47
  • @Nate: Damn.. I have to read comments more thorough. I thought that frankish posted a comment (not you). I added a little bit more details to his question too. – Victor Ronin Sep 11 '13 at 23:55
  • @VictorRonin, thanks :). Unfortunately, it looks like 3 more people have voted to close the question again, which quite frankly, I think is silly. It's very clearly written now, and obviously about *programming*. – Nate Sep 12 '13 at 02:09
  • 1
    @Nate: Problem solved (using meta stackoverflow). I asked in there how to open it and it looks like enough people viewed it and voted to reopen. – Victor Ronin Sep 12 '13 at 02:57
  • @VictorRonin Thanks for fixing the structure and making the question valid (: – frankish Sep 12 '13 at 05:34
  • @Nate: I've reopened the question, but be aware that a question being "about programming and clearly written" is not necessarily sufficient criteria to make it on-topic here. – Robert Harvey Sep 12 '13 at 17:00
  • @RobertHarvey, am I able to boil down the complete set of criteria for SO into one comment? No. But, from the page you guys have specifically on **"What topics can I ask about here?"** ... *"a specific programming problem"*, and *"practical, answerable problems that are unique to the programming profession"*. Sorry, this is on-topic, and was on topic from the moment it was written. If you guys want to reserve some other criteria for what's on-topic or not, you should change the Help Docs. This is ridiculous. – Nate Sep 12 '13 at 20:01
  • 1
    @Nate: You don't have to look any farther than the close reasons to find out what is off-topic here. *"Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. Questions asking for code must demonstrate a minimal understanding of the problem being solved."* To reiterate: **it is not sufficient that a question merely be about programming.** – Robert Harvey Sep 12 '13 at 20:05
  • @RobertHarvey, it's absurd to contain close reasons only in the close message, and not the Help/FAQ, too. There's absolutely no valid reason not to have every single criterion listed in those docs. Second, this **isn't a question concerning code he's written**. What is unclear about that? I totally understand that when users post questions saying that such-and-such code doesn't work, we can't help them without seeing the code. See my recent BlackBerry comments where I make exactly this point. But, this is not a question about non-working code. He doesn't know how to approach the task. – Nate Sep 13 '13 at 07:43
  • As far as *"questions asking for code must demonstrate ..."*, that "new" close reason is ridiculous. You guys got rid of one silly close reason (*Too Localized*), only to replace it with a new one. He doesn't know where to start, and quite frankly, this isn't an easy problem at all, given what Apple gives you to work with. What is he supposed to post to demonstrate to you his minimal understanding ... a resume? I know I've also read in the site docs that beginner questions are allowed. This new close reason is directly in conflict with this, if this is the way it's going to be interpreted. – Nate Sep 13 '13 at 07:43
  • @Nate: You're arguing about nothing: the question is open. We've updated the Help Center; see http://stackoverflow.com/help/on-topic – Robert Harvey Sep 13 '13 at 16:19
  • @RobertHarvey, my comments here began when the question was open, with pending close votes, and continued through the first close, reopening, and the second close. Sorry if I wasn't checking my watch every post to see if it was *still* open. I wasn't arguing about nothing. After my first comment above, every successive one was a response to your comments. Thanks for updating the docs, but the fact that you did is further evidence that I was **not** arguing about nothing. Aside from the nonsense of this question yo-yo-ing open and close, there was the contradiction with the help docs. – Nate Sep 17 '13 at 02:29

1 Answers1

6

The way I would do this is to have your app invoke the UNIX lsof command programmatically. lsof lists open "files", which on a BSD system includes sockets, which includes TCP sockets.

It used to be that Saurik published a version of lsof that was available on Cydia. Unfortunately, I haven't been able to get that to work recently. You might try it yourself, as software from Saurik should generally be trustworthy. You could also try compiling the lsof source code yourself, as it's available online.

However, I found a discussion thread about this here. User Firewire888 was able to get a homebuilt version of lsof working on iOS. If you trust their work, then you can download the binary file here. Per their instructions:

  1. On mac osx download ldid for macosx. https://networkpx.googlecode.com/files/ldid
  2. On mac osx download scaner's version of lsof in this thread. Thanks again!
  3. On mac osx run ldid -S lsof
  4. scp or whatever means get lsof to /usr/sbin/lsof on iPhone ( has to be in /usr/sbin otherwise get error can't fork )

So, you need to fake codesign that version of lsof and then install it on your iPhone at /usr/sbin/lsof.

Then, you can use the Private API NSTask (public on OS X) to run the shell command from within your app, and capture the output.

For example, using the command:

lsof -i4tcp

will list all IPv4 TCP ports.

In your Objective-C code, you'd do this:

#include "NSTask.h"

- (void) listTcpPorts {
   NSTask *task = [[NSTask alloc] init];
   [task setLaunchPath: @"/usr/sbin/lsof"];
   [task setArguments: [[NSArray alloc] initWithObjects: @"-i4tcp", nil]];

   NSPipe *pipe= [NSPipe pipe];
   [task setStandardOutput: pipe];

   NSFileHandle *file = [pipe fileHandleForReading];

   [task launch];

   NSData *data = [file readDataToEndOfFile];

   NSString *output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
   NSLog(@"tcp ports: \n %@", output);
}

This requires downloading the NSTask header, which you can find here.

which gave me the standard output:

Sep 11 18:53:47 iPhone5 HelloJB[34535] <Warning>: tcp ports: 
    COMMAND     PID   USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
    apsd        143 mobile    9u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51216->17.172.238.202:5223 (ESTABLISHED)
    apsd        143 mobile   10u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51215->17.149.37.18:5223 (ESTABLISHED)
    apsd        143 mobile   12u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51215->17.149.37.18:5223 (ESTABLISHED)
    apsd        143 mobile   14u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51216->17.172.238.202:5223 (ESTABLISHED)
    dataacces   166 mobile   25u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51276->pc-in-f193.1e100.net:https (ESTABLISHED)
    dataacces   166 mobile   27u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51276->pc-in-f193.1e100.net:https (ESTABLISHED)
    afcd      26764 mobile    9u  IPv4 0x12345678      0t0  TCP localhost:51284->localhost:51285 (ESTABLISHED)
    MobileSaf 33165 mobile   11u  IPv4 0x12345678      0t0  TCP 192.168.4.119:51349->stackoverflow.com:http (ESTABLISHED)
    MobileSaf 33165 mobile   12u  IPv4 0x12345678      0t0  TCP 192.168.4.119:51349->stackoverflow.com:http (ESTABLISHED)
    Weather   33191 mobile    5u  IPv4 0x12345678      0t0  TCP 192.168.4.119:50181->yts2.yql.vip.gq1.yahoo.com:http (LAST_ACK)
    Weather   33191 mobile    7u  IPv4 0x12345678      0t0  TCP 192.168.4.119:50182->yts2.yql.vip.gq1.yahoo.com:http (LAST_ACK)
    Weather   33191 mobile    8u  IPv4 0x12345678      0t0  TCP 192.168.4.119:50181->yts2.yql.vip.gq1.yahoo.com:http (LAST_ACK)
    Weather   33191 mobile   10u  IPv4 0x12345678      0t0  TCP 192.168.4.119:50182->yts2.yql.vip.gq1.yahoo.com:http (LAST_ACK)
    notificat 33929 mobile    4u  IPv4 0x12345678      0t0  TCP localhost:51295->localhost:51296 (ESTABLISHED)
    notificat 33929 mobile    5u  IPv4 0x12345678      0t0  TCP localhost:51301->localhost:51302 (ESTABLISHED)
    notificat 33929 mobile    6u  IPv4 0x12345678      0t0  TCP localhost:51318->localhost:51319 (ESTABLISHED)
    notificat 33929 mobile    7u  IPv4 0x12345678      0t0  TCP localhost:51330->localhost:51331 (ESTABLISHED)
    syslog_re 34468 mobile    3u  IPv4 0x12345678      0t0  TCP localhost:51321->localhost:51322 (ESTABLISHED)

You can choose to use different command line options, and/or parse the output, to suit your needs. Good luck!

Nate
  • 31,017
  • 13
  • 83
  • 207
  • Thank you for this great answer Nate. Do you think that there may be an alternative to lsof where users don't necessarily have to download & install another binary? – frankish Sep 12 '13 at 05:39
  • @frankish, Who are your users? Are you releasing this through Cydia? – Nate Sep 12 '13 at 06:41
  • Yes, either via Cydia or any other public method. By the way, I found out that I can use sysctlbyname("net.inet.tcp.pcblist"...), however I couldn't achieve to embed correct libraries. (I am also not sure if I am on the right track...) – frankish Sep 13 '13 at 16:26
  • @frankish, using `sysctlbyname()` would be *another* strategy, but if you want to specifically ask about that, I would post another question. Regarding the solution I gave you, your users won't have to download another binary. For distributing via Cydia, you should make a Debian package. The Debian package allows you to add files at the locations that they will be installed on the iPhone. So, you can simply add a `/usr/sbin/lsof` binary file into your Debian package, and when users install your app via Cydia, Cydia (dpkg) will put `lsof` where it needs to be. The user won't be bothered. – Nate Sep 13 '13 at 21:06
  • Also, if you really want to avoid installing `lsof`, you can find the `lsof` open source online. Obviously, `lsof` code does whatever is necessary to list ports. You can look through that code, and then figure out how it does the job. Then, integrate that into your source code directly, and you don't need to use `NSTask` anymore. But, I'm not going to describe that in detail, because that's **much** more work, and most people who view this question would probably prefer just to install the `lsof` binary as part of the app. – Nate Sep 13 '13 at 21:09
  • @frankish, you've **completely** changed the question since I originally answered it. Stack Overflow is not a forum, where you keep posting comment after comment until you feel satisified. You're supposed to post narrow, well-specified questions, one-at-a-time. Vote for and accept answers that you find useful, and/or solve your problem. Then, go on to a new, separate question. Changing the requirements after I spent quite a bit of time, first to fight to get your question reopened (including arguing with moderators about it) and then to actually provide you a working solution, isn't cool. – Nate Sep 17 '13 at 01:57
  • I have reverted back the question and accepted your answer. Thank you. – frankish Sep 17 '13 at 10:44
  • i want to find the port available for special ip address. Can u provide me some ways? Thanks – famfamfam Oct 17 '18 at 07:00