HowTo: Bind to a specific network interface

Ask for help and report issues with the Mac OS X version of Transmission
Smudge
Posts: 3
Joined: Thu Mar 17, 2011 5:19 am

HowTo: Bind to a specific network interface

Post by Smudge »

I wanted to configure Transmission to use a specific network interface, specifically a secure VPN connection, but the Mac GUI doesn't have such an option within the preferences.

The wiki mentions using a 'bind-address-ipv4' option to have Transmission bind to a specific IP address of a network interface. I tried entering this option within the preferences plist file but it still didn't work. After a long time digging thru the source code (thanks for making that available!), I found the section that loads the plist file and saw that the Mac GUI option has a slightly different option spelling of BindAddressIPv4. Adding the properly named option and the IP address of my VPN, Transmission properly bound to that network and all traffic is going over it! :D

So, how do you do it? First, quit Transmission as you don't want to edit the config file while it is running. Transmission saves to it on quit so any changes you make while it is open will be overwritten.

You can either edit the plist file using the Property List Editor program, if you have the Apple Developer's Tools package (aka XCode and friends) installed, or Terminal command line using the defaults command. I'll show you both.

The plist file is located at ~/Library/Preferences/org.m0k.transmission.plist. You might want to make a backup copy of it before you start messing around with it.

If you have the DevTools, Property List Editor is located at /Developer/Applications/Utilities/Property List Editor. Either open it directly or right click on the plist file and choose Open With and Property List Editor should be an option.
When Property List Editor opens the plist file, it should have the Root dictionary selected. Simply click on the Add Child button which will create a New Item entry. Simply rename the item key to BindAddressIPv4 (case matters!) and press Tab to jump over to the Value field. Here you will enter the IP address of the interface you want to use. Make sure the Type remains a String.

Here is what mine looks like.

Image

Simply quit Property List Editor, saving the plist, then launch Transmission and it will bind to that IP address.

You can see this at the very beginning of the Debug level of the Window>Message Log.

Code: Select all

2011-03-16 23:04:43 -0600 net.c:414 [Debug] Transmission: Bound socket 11 to port 49921 on 69.80.103.21
And if you really want, you can confirm it from a Terminal command line using the 'lsof -i' command, which lists your open network connections.


If you don't have the DevTools installed, you can use the Terminal program located at /Applications/Utilities/Terminal.
Simply run Terminal then type in defaults write org.m0k.transmission bind-address-ipv4 69.80.103.21 but exchanging my example IP address (in red) for your interface's IP address. When you press enter, it should come back to a prompt with no errors. Simply quit Terminal and launch Transmission.


Finally, you can also bind to a IPv6 address but using the BindAddressIPv6 option and proper v6 IP address. I'm not lucky enough to have IPv6 yet so I couldn't test it.


The Downsides!

1- If the interface/IP address is not available (ie, the VPN isn't established) then Transmission will not fallback to the primary connection but just sit there trying over and over to bind. You will only see this if you open the Message Log. You will need to re-establish the connection or remove the binding option using defaults delete org.m0k.transmission bind-address-ipv4 or using Property List Editor.

2- The automatic port mapping function within Transmission still found my default internet gateway (10.9.9.1) and configured the open port mapping in my modem. Since Transmission isn't listening on that interface, the peer listening port is closed thus severely limiting my peer connections.

Code: Select all

2011-03-16 23:04:47 -0600 upnp.c:113 [Info] Port Forwarding (UPnP): Found Internet Gateway Device "http://10.9.9.1:5555/ctl/IPConn"
2011-03-16 23:04:47 -0600 upnp.c:115 [Info] Port Forwarding (UPnP): Local Address is "10.9.9.21"
2011-03-16 23:04:47 -0600 upnp.c:221 [Info] Port Forwarding (UPnP): Port forwarding through "http://10.9.9.1:5555/ctl/IPConn", service "urn:schemas-upnp-org:service:WANIPConnection:1". (local address: 10.9.9.21:49921)
2011-03-16 23:04:47 -0600 upnp.c:224 [Info] Port Forwarding (UPnP): Port forwarding successful!
At least in my situation, it is an external VPN so I can't configure port mapping. If you have control of the gateway device (modem/router) for your alternate interface, you will need to manually open the port so that the peers can get in.


Good luck and I hope this helps.
atm999
Posts: 8
Joined: Sat Feb 19, 2011 10:30 am

Re: HowTo: Bind to a specific network interface

Post by atm999 »

Good tips, but what this is really doing is binding to an IP address. If you use DHCP (don't have a static IP), then this will stop working when your IP address changes. What you need to do to actually bind to an interface (rather than an IP address) is wait for trac ticket #2313 to be implemented, or compile the patch file yourself.
atm999
Posts: 8
Joined: Sat Feb 19, 2011 10:30 am

Re: HowTo: Bind to a specific network interface

Post by atm999 »

x190 wrote:
atm999 wrote:Good tips, but what this is really doing is binding to an IP address. If you use DHCP (don't have a static IP), then this will stop working when your IP address changes.
atm999: Could you please elaborate? What exactly will stop working when the users IP address changes?
Because this setting binds to a specific IP address, if that IP address is not found on a local network interface then no data will be sent at all. This can happen if you get your IP address through DHCP instead of having a static IP.
atm999
Posts: 8
Joined: Sat Feb 19, 2011 10:30 am

Re: HowTo: Bind to a specific network interface

Post by atm999 »

x190 wrote:He is talking about binding to the IP address of his VPN server, correct? His own IP address is not involved as far as Transmission is concerned. Isn't the real concern, the question of what happens when the VPN network goes down. In that case, then "Transmission will not fallback to the primary connection but just sit there trying over and over to bind" from "Downsides 1" above would kick in, which is good, except T needs to break out of that code loop and pause the torrents.

Or, have I misunderstood something?
You have not misunderstood him. Everything you just said is correct, but there is more to it. When you bind to a normal network interface and not a VPN, if you have a dynamic (DHCP) IP address the problem I described will occur, where no data will be sent if your IP changes. It's the same issue that the OP described in downside 1, but in a different situation.
bazzardl
Posts: 3
Joined: Fri Oct 21, 2011 8:04 am

Re: HowTo: Bind to a specific network interface

Post by bazzardl »

Hi, I have been trying to solve this with an applescript so I posted this problem on the apple support boards

https://discussions.apple.com/message/16465964#16465964

Camelot pointed my at the solution:

on idle
set activeInterfaces to do shell script "ifconfig -lu"
if activeInterfaces is not "lo0 en0 fw0 en1 utun0 tun0" then
tell application "Transmission" to quit
end if
return 10 -- 30 is default value, but it doesn't hurt to include it here
end idle

to get this to work change "lo0 en0 fw0 en1 utun0 tun0" to whatever you get when you run 'ifconfig -lu' in terminal when VPN is running. I use the HMA Pro VPN cline t for mac and when VPN is down tun0 is not in the active interfaces so the script will tell transmission to quit. Change the 10 to whatever number you like (I like to have it rerun every 10 seconds)
bigugly
Posts: 3
Joined: Sat May 19, 2012 11:09 am

Re: HowTo: Bind to a specific network interface

Post by bigugly »

Try this just change "Name of VPN Connection" to whatever your connection is called. You have to ad the "BindAddressIPv4" to org.m0k.transmission.plist as a string. You also need to set tell the script the name of your interface by changing Name of Interface.

Code: Select all

--checks to see if VPN is connected, reconnects VPN if needed and quits then restarts Transmission binded to the VPNs new IP address
on idle
	--Checks every 10 seconds to see if the VPN is still connected
	tell application "System Events"
		tell current location of network preferences
			set myConnection to the service "Name of VPN Connection"
			if myConnection is not null then
				if current configuration of myConnection is not connected then
					connect myConnection
					--Waits 10 seconds to give VPN a chance to reconnect
					delay 10
					--Quits Transmission ready for the .plist change
					set app_name to "Transmission"
					set the_pid to (do shell script "ps ax | grep " & (quoted form of app_name) & " | grep -v grep | awk '{print $1}'")
					if the_pid is not "" then do shell script ("kill -9 " & the_pid)
					--Gets the IP address of interface Name of Interface
					set myIP to do shell script "ifconfig Name of Interface|grep 'inet '|cut -d ' ' -f 2"
					--Sets the path to Transmission .plist then sets IP address to value of BindAddressIPv4
					set thePListPath to ("~/Library/Preferences/org.m0k.transmission.plist")
					tell application "System Events"
						tell property list file thePListPath
							tell contents
								set value of property list item "BindAddressIPv4" to myIP
								--Brings Transmission back up with new IP address
								tell application "Transmission" to activate
							end tell
						end tell
					end tell
				end if
			end if
		end tell
		return 10
	end tell
end idle
atm999
Posts: 8
Joined: Sat Feb 19, 2011 10:30 am

Re: HowTo: Bind to a specific network interface

Post by atm999 »

Where should this code be added? Thanks!
bigugly wrote:Try this just change "Name of VPN Connection" to whatever your connection is called. You have to ad the "BindAddressIPv4" to org.m0k.transmission.plist as a string. You also need to set tell the script the name of your interface by changing Name of Interface.

Code: Select all

--checks to see if VPN is connected, reconnects VPN if needed and quits then restarts Transmission binded to the VPNs new IP address
on idle
	--Checks every 10 seconds to see if the VPN is still connected
	tell application "System Events"
		tell current location of network preferences
			set myConnection to the service "Name of VPN Connection"
			if myConnection is not null then
				if current configuration of myConnection is not connected then
					connect myConnection
					--Waits 10 seconds to give VPN a chance to reconnect
					delay 10
					--Quits Transmission ready for the .plist change
					set app_name to "Transmission"
					set the_pid to (do shell script "ps ax | grep " & (quoted form of app_name) & " | grep -v grep | awk '{print $1}'")
					if the_pid is not "" then do shell script ("kill -9 " & the_pid)
					--Gets the IP address of interface Name of Interface
					set myIP to do shell script "ifconfig Name of Interface|grep 'inet '|cut -d ' ' -f 2"
					--Sets the path to Transmission .plist then sets IP address to value of BindAddressIPv4
					set thePListPath to ("~/Library/Preferences/org.m0k.transmission.plist")
					tell application "System Events"
						tell property list file thePListPath
							tell contents
								set value of property list item "BindAddressIPv4" to myIP
								--Brings Transmission back up with new IP address
								tell application "Transmission" to activate
							end tell
						end tell
					end tell
				end if
			end if
		end tell
		return 10
	end tell
end idle
bigugly
Posts: 3
Joined: Sat May 19, 2012 11:09 am

Re: HowTo: Bind to a specific network interface

Post by bigugly »

You need to copy then paste it into AppleScript editor make the changes then save and run it
atm999
Posts: 8
Joined: Sat Feb 19, 2011 10:30 am

Re: HowTo: Bind to a specific network interface

Post by atm999 »

I don't suppose there's an easy way to port this to the Linux version (i.e. Transmission Daemon) since it obviously doesn't support AppleScript? Thanks again!
bigugly wrote:You need to copy then paste it into AppleScript editor make the changes then save and run it
bigugly
Posts: 3
Joined: Sat May 19, 2012 11:09 am

Re: HowTo: Bind to a specific network interface

Post by bigugly »

I'm sure it could be, the guts of it are done at the shell, shouldn't be to much work to write a shell script which does the same thing.
What you really need to do is google each part of what you want to do in sequence then put it all together the comments in my script should help.
torrentrabbit
Posts: 2
Joined: Sun Jun 10, 2012 9:40 pm

Re: HowTo: Bind to a specific network interface

Post by torrentrabbit »

Hello!

Thought I'd bump this thread/add three questions, as it seems to pertain EXACTLY to what I'm looking to do (and thanks to Smudge for starting the thread and posting the developer tools solution).

Background: I am a VERY casual user who occasionally opens things up to look at them, but who needs a little hand-holding to accomplish things. So if I mostly use my Mac as an appliance, I'm happy opening it up as one would a watch or a toaster, and I have a VERY rudimentary grasp of things, on the level of "Don't touch the red wire!", but that's about it.

I am using OS 10.6.8 and Transmission 2.52 (13304). After my ISP began screwing severely with my connection, I subscribed anonymously to a Swedish VPN. It is reliable, has not dropped my connection, is fast … but there are reasons to route my non-torrent traffic through my regular USA ISP, such as using Netflix and other services limited by geographic location. My VPN has servers in Sweden only, so using a USA IP via my VPN is not an option; and besides, there's just something about the principle of splitting my traffic and still using my ISP for regular tasks (the bastards) that appeals to me.

1) If I understand correctly, I can open the Transmission plist file and use Property List Editor to "Add Child" BindAddressIPv4, plus my VPN's IP, in order to bind Transmission to the VPN only. Could I instead bind Transmission to the "interface"? Again, I'm a noob. I'm looking at something called IPNet Monitor X and it seems to be calling my VPN "interface (ppp1)". My gut tells me that, if my Swedish VPN ever sends me a different IP, binding to this "interface (ppp1)" thing would be a way to still bind to that IP without having to type it in specifically, or retype it if it changes. If so, when I "Add Child", would my "child" be called something other than BindAddressIPv4?

2) I may NOT be understanding a secondary problem you outlined, Smudge: You state that "the peer listening port is closed thus severely limiting my peer connections". Does this mean I would be only downloading, not uploading? That seems like it would be a breach of etiquette on my part, if I were downloading only and not uploading; I think I'm misunderstanding, though. Either way, did you find a solution to this problem? Can I impose on your patience and ask you to describe it again?

3) Once having bound Transmission to my VPN, I'm unclear how to route the rest of my traffic "out" through my regular ISP''s IP. When I set up my VPN using OS 10.6.8's native client in System Preferences, under Network > [my vpn] > Advanced > Options, I was instructed to check the "Send all traffic over VPN connection" box. Having changed its plist to bind Transmission to the VPN, will unchecking this box route my regular traffic out through my stupid ISP's IP addie, while Transmission's continues to zip through the VPN?

Again, thank you so much to the OP and to all posters for this thread, I understand my knowledge is limited, so all gratitude for your patience and for any replies you may be able to provide, and as a noob, let me say: these fancy typewriters are FUN! =]
torrentrabbit
Posts: 2
Joined: Sun Jun 10, 2012 9:40 pm

Re: HowTo: Bind to a specific network interface

Post by torrentrabbit »

When I tried a VPN, everything was routed through the VPN by default, as I recall. Your best answer will come from your own testing on the US specific sites. Please let us know.
Turns out, in fact, that deselecting "Send all traffic over VPN connection" in OS 10.6.8 "System Preferences > Network > [my vpn] > Advanced > Options" will keep the VPN open, running silently in the background, but all regular traffic will go out via my suck-ass provider's USA IP.

Then, when I implement Smudge's suggestion to use "/Developer/Applications/Utilities/Property List Editor" to edit the "~/Library/Preferences/org.m0k.transmission" plist file and Add Child "BindAddressIPv4 = [my vpn's IP]", all my Transmission traffic goes out through my beautiful, Swedish VPN's IP address while my other traffic continues to route out through my USA ISP.

So the solution seems to create a cobbled-together split-tunnel, in effect?

Since my VPN connection hasn't gone down in a while -- in fact, not once since I've started it, other than when I've chosen to disconnect -- the need for a way to bind to ppp1 rather than to a specific IP address doesn't seem that great, but it would still be a neat trick. I will look through the ticket you linked to, but I know I've run into it and read through it quickly once before (when I was impatient and anxious for a quick fix), and much of it was over my head. I will read through it again, however, now that the urgency has passed, and see if I with more careful scrutiny I can parse something from it that I can learn something from.

Thanks for the link and the feedback!
missiontrans
Posts: 2
Joined: Wed Aug 22, 2012 2:44 pm

Re: HowTo: Bind to a specific network interface

Post by missiontrans »

hello,

i took the tips for binding the ip of my vpn connection of this thread and combined it with applescript and growl notification. and it appears to be working just fine, so i thought a share it with you.

basics: i use OS: 10.8. VPN Client : viscosity 1.4.1 an older but free version of Growl 1.2.2. PLIST Editor: Pref Setter 2.0 and Transmission 2.6.1

i followed smudges tutorial for altering the org.m0k.transmission by using the Pref Setter plist editor. First i tried to set the value to my external ip, while connected to my vpn provider, but no success. In the viscosity vpn client -> connection details ip addresses for "server ip" and "client ip" are shown. with the "client ip" the ipv4binding is successful.

so far so good. tinkering around i wanted an automated solution, since my vpn service has numerous gateway servers. since viscosity provides support for applescript i tried my luck. i had the following in mind: run applescript after connection is established, get the "client ip" (external ip) for the ipv4binding automatically and write the string value in the org.m0k.transmission.plist.

so next step: getting the ip of my virtual network interface, in my case "tun0" --> Terminal command: ifconfig ----- too much information, i want only the "naked" ip of "tun0".
The command: " ifconfig tun0 | grep inet | awk '{print $2}' " gives you exactly that

turns out the output of that command is what viscosity displays as "client ip"

again borrowing from smudges tutorial and combining with applescript:

do shell script "defaults write org.m0k.transmission BindAddressIPv4 `ifconfig tun0 | grep inet | awk '{print $2}'`"

this writes your tun0 external ip of the current active vpn connection in your org.m0k.transmission.plist

so thanks to smudge

before i threadjack here and "spam" with my personalised solution....but if somebody is interested in how i combined all that plus growl notification for successful and failed ipv4binding in one nice applescript, let me know.

cheers ;)
zyps
Posts: 1
Joined: Thu Aug 30, 2012 2:11 pm

Re: HowTo: Bind to a specific network interface

Post by zyps »

I'd love to know how you did it if you wouldnt mind sharing :)
missiontrans
Posts: 2
Joined: Wed Aug 22, 2012 2:44 pm

Re: HowTo: Bind to a specific network interface

Post by missiontrans »

Hi,

well i'd like to share. I currently use the following script: simply open applescript editor and paste the following, save as script and you should be ready to go.

Code: Select all

tell application "System Events" to (name of processes) contains "Transmission"

set transmissionisrunning to the result

if transmissionisrunning = true then #determine if transmission already runs
	
	do shell script "killAll Transmission" #if so, then simply kills it
	
end if

do shell script "defaults delete org.m0k.transmission BindAddressIPv4" #delete previously written ipv4binding value

do shell script "defaults write org.m0k.transmission BindAddressIPv4 `ifconfig tun0 | grep inet | awk '{print $2}'`" #get current ip of vpn interface and write it into .plist

do shell script "defaults read org.m0k.transmission BindAddressIPv4" #read out the just written ipv4 binding

set ip4binding to the result

do shell script "ifconfig tun0 | grep inet | awk '{print $2}'" #read out again the vpn interface ip

set vpnip to the result

ip4binding = vpnip #compare both values

set ip_comparison to the result

if ip_comparison = true then #determine if both values are the same
	
	tell application "Growl" #getting growl to display the succeeful outcome 
		set the allNotificationsList to {"IPv4 Binding", "IPv4 Binding Failed"}
		set the enabledNotificationsList to {"IPv4 Binding"}
		register as application "IPv4 Binding" all notifications allNotificationsList default notifications enabledNotificationsList
		notify with name "IPv4 Binding" title "IPv4 Binding" description ip4binding application name ¬
			"IPv4 Binding" icon of application "Transmission.app"
	end tell
	
else
	
	tell application "Growl" ##getting growl to display the failed outcome
		set the allNotificationsList to {"IPv4 Binding", "IPv4 Binding Failed"}
		set the enabledNotificationsList to {"IPv4 Failed"}
		register as application "IPv4 Binding" all notifications allNotificationsList default notifications enabledNotificationsList
		notify with name "IPv4 Binding Failed" title "IPv4 Binding" description "Failed" application name ¬
			"IPv4 Binding" icon of application "Transmission.app"
		
	end tell
	
end if

tell application "Transmission" to activate #launch/relaunch transmission


use this script in the viscosity preferences / connections -> advanced "after connection" (i am not sure about the english localization, since i am using a german one (Einstellungen (preferences) -> Verbindungen (connection) -> for each specific connection Bearbeiten (edit) -> erweitert (advanced) -> voilá


i hope this works for you too.

cheers
Post Reply