HowTo: Bind to a specific network interface

Ask for help and report issues with the Mac OS X version of Transmission
missiontrans
Posts: 2
Joined: Wed Aug 22, 2012 2:44 pm

Re: HowTo: Bind to a specific network interface

Post by missiontrans » Wed Aug 22, 2012 3:17 pm

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 » Thu Aug 30, 2012 2:44 pm

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 » Sat Sep 01, 2012 4:13 pm

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

<br >
Posts: 5
Joined: Sun Sep 02, 2012 7:00 am

Re: HowTo: Bind to a specific network interface

Post by <br > » Sun Sep 02, 2012 8:39 am

torrentrabbit wrote:
Since my VPN connection hasn't gone down in a while ...
No one has mentioned where to input one's VPN user/pw credentials?

abusyman
Posts: 1
Joined: Fri Sep 28, 2012 6:28 am

Re: HowTo: Bind to a specific network interface

Post by abusyman » Fri Sep 28, 2012 6:33 am

missiontrans wrote:Hi,

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

This script worked for me, and it appears that Transmission is bound to the local VPN IP address via the "BindAddressIPv4" preference. However, I am unable to get Transmission to work now. It works great with my VPN if i route all traffic through it, but not using this method. Are there some other settings I am forgetting to change?

brutalspoon
Posts: 1
Joined: Mon Dec 24, 2012 6:38 pm

Re: HowTo: Bind to a specific network interface

Post by brutalspoon » Mon Dec 24, 2012 8:00 pm

I managed to get this working and thought I'd share it here for anybody else who stumbled across it. It takes a slightly different approach, so see what works best for you.

As a disclaimer, this works for PPTP connections set up using the network prefpane in System Preferences. I'm sure you could get it working with an OpenVPN client, but I'm not sure how you'd do that.

I'm using a modified AppleScript application - the bulk of the original code was written by Jack0817 on the µTorrent forums, so most of the credit goes to him. I just changed the application to Transmission and added some code to grab the VPN's current IP address and edit the plist file (so that if the VPN goes down for any reason Transmission INSTANTLY stops downloading), similar to some of the other solutions.

The script runs every 60 seconds and checks if the VPN is connected. If it's not, it closes Transmission and attempts to reconnect to the VPN. Once the VPN is reconnected it will get the VPN's IP address, bind Transmission to this IP address, then start Transmission up again. Because Transmission doesn't start unless the VPN is fully connected, the script usually needs to cycle twice if the VPN disconnects; once to reconnect to the VPN and then again to start Transmission. Even so, this ensures that (assuming you have no connection problems with your VPN) your torrents will only be down for 2 minutes.

You'll need to add BindAddressIPv4 to the Transmission plist file first (as covered in the earlier posts first), then save this script as an application (make sure you check "Stay open after run handler") and, if you like, set it run on startup:

Code: Select all

------------------------------------------------
--Main Routine
------------------------------------------------
on idle
	
	--Script Variables
	set appName to "Transmission"
	set vpnName to "NAME_OF_VPN" -- Enter the name of your VPN service as it
	set waitTIme to 60 as integer -- appears in your Network preferences
	
	--Main Script Logic
	if isVPNConnected(vpnName) then
		startApplication(appName)
	else
		stopApplication(appName)
		connectVPNConnection(vpnName)
	end if
	
	return waitTIme
	
end idle

------------------------------------------------
--Sub Routine - Determines if specified vpn is connected
------------------------------------------------
on isVPNConnected(vpnName)
	
	--Init return value to default
	set isConnected to false
	
	tell application "System Events"
		tell current location of network preferences
			set vpnConnection to the service vpnName
			set isConnected to current configuration of vpnConnection is connected
		end tell
	end tell
	
	return isConnected
	
end isVPNConnected

------------------------------------------------
--Sub Routine - Attempts to connect to the specified VPN
------------------------------------------------
on connectVPNConnection(vpnName)
	
	tell application "System Events"
		tell current location of network preferences
			set vpnConnection to the service vpnName
			if vpnConnection is not null then
				connect vpnConnection
			end if
		end tell
	end tell
	
end connectVPNConnection

------------------------------------------------
--Sub Routine - Starts an application if it is not already running
------------------------------------------------
on startApplication(appName)
	
	if appIsRunning(appName) is false then
		set vpnAddress to (do shell script ("/sbin/ifconfig ppp0 | grep 'inet ' | cut -d' ' -f 2")) -- change ppp0 to vpn interface in ifconfig if needed
		tell application "System Events"
			set plistFile to property list file "/Users/robroy/Library/Preferences/org.m0k.transmission.plist"
			tell plistFile
				set value of property list item "BindAddressIPv4" to vpnAddress
			end tell
		end tell
		tell application appName to activate
	end if
	
end startApplication

------------------------------------------------
--Sub Routine - Stop an application if it is running
------------------------------------------------
on stopApplication(appName)
	
	if appIsRunning(appName) then
		tell application appName to quit
	end if
	
end stopApplication

------------------------------------------------
--Sub Routine - Determines if specified app is currently running
------------------------------------------------
on appIsRunning(appName)
	
	set isRunning to false
	
	tell application "System Events"
		set isRunning to (name of processes) contains appName
	end tell
	
	return isRunning
	
end appIsRunning
Two last things - first, you'll want to make sure that you've disabled any warnings about closing Transmission (otherwise the script will hang as Transmission asks you if you want to close with active transfers).

Second, if you want to make Transmission launch on startup, use this script instead of adding Transmission itself to the login items. This will ensure that the VPN is fully started (and that you have the VPNs current IP address in Transmission's plist file).

EDIT: Updated link to µTorrent forums thread so that it points to Jack0817's post.

ajohansson
Posts: 5
Joined: Thu Feb 21, 2013 4:33 pm

Re: HowTo: Bind to a specific network interface

Post by ajohansson » Thu Feb 21, 2013 4:50 pm

Hi can anyone tell me how much of the script I need to edit. Im new to this. below is my script edited. When I launch the app a pop up says that the variable SwissVPN which is the name of my VPN is not defined. Any help appreciated.

------------------------------------------------
--Main Routine
------------------------------------------------
on idle

--Script Variables
set appName to "Transmission"
set vpnName to "NAME_OF_VPN" -- Enter the name of your VPN service as it
set waitTIme to 60 as integer -- appears in your Network preferences

--Main Script Logic
if isVPNConnected(SwissVPN) then
startApplication(Transmission)
else
stopApplication(Transmission)
connectVPNConnection(SwissVPN)
end if

return 30

end idle

------------------------------------------------
--Sub Routine - Determines if specified vpn is connected
------------------------------------------------
on isVPNConnected(SwissVPN)

--Init return value to default
set isConnected to false

tell application "System Events"
tell current location of network preferences
set vpnConnection to the service SwissVPN
set isConnected to current configuration of vpnConnection is connected
end tell
end tell

return isConnected

end isVPNConnected

------------------------------------------------
--Sub Routine - Attempts to connect to the specified VPN
------------------------------------------------
on connectVPNConnection(SwissVPN)

tell application "System Events"
tell current location of network preferences
set vpnConnection to the service SwissVPN
if vpnConnection is not null then
connect vpnConnection
end if
end tell
end tell

end connectVPNConnection

------------------------------------------------
--Sub Routine - Starts an application if it is not already running
------------------------------------------------
on startApplication(Transmission)

if appIsRunning(Transmission) is false then
set vpnAddress to (do shell script ("/sbin/ifconfig ppp0 | grep 'inet ' | cut -d' ' -f 2")) -- change ppp0 to vpn interface in ifconfig if needed
tell application "System Events"
set plistFile to property list file "/Users/atjohansson/Library/Preferences/org.m0k.transmission.plist"
tell plistFile
set value of property list item "BindAddressIPv4" to vpnAddress
end tell
end tell
tell application Transmission to activate
end if

end startApplication

------------------------------------------------
--Sub Routine - Stop an application if it is running
------------------------------------------------
on stopApplication(Transmission)

if appIsRunning(Transmission) then
tell application Transmission to quit
end if

end stopApplication

------------------------------------------------
--Sub Routine - Determines if specified app is currently running
------------------------------------------------
on appIsRunning(Transmission)

set isRunning to false

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

return isRunning

end appIsRunning

ajohansson
Posts: 5
Joined: Thu Feb 21, 2013 4:33 pm

Re: HowTo: Bind to a specific network interface

Post by ajohansson » Thu Feb 21, 2013 7:57 pm

I opened up Vuze and found out how to do it internally there and tested it and it works. Would love for transmission to have this type of safety catch.

ajohansson
Posts: 5
Joined: Thu Feb 21, 2013 4:33 pm

Re: HowTo: Bind to a specific network interface

Post by ajohansson » Thu Feb 21, 2013 8:56 pm

well after more research looks like there is a way to do this. I used the patch from this ticket thread

https://trac.transmissionbt.com/ticket/2313

added BindInterface and put ppp0 in the string and it works perfectly. well I thought I download, turn off vpn and it stops, then finds my other network for some reason and connects. looks like its vuze till if figure this out.

x190
Posts: 5094
Joined: Sun Nov 30, 2008 4:59 am

Re: HowTo: Bind to a specific network interface

Post by x190 » Sun Mar 03, 2013 3:50 am

ajohansson wrote:well after more research looks like there is a way to do this. I used the patch from this ticket thread

https://trac.transmissionbt.com/ticket/2313

added BindInterface and put ppp0 in the string and it works perfectly. well I thought I download, turn off vpn and it stops, then finds my other network for some reason and connects. looks like its vuze till if figure this out.
Try adding BindAddressIPv4 ([EDIT]and 6, if applicable) and setting any [EDIT] non-routable address to keep T away from 0.0.0.0 [EDIT] or :: .
Last edited by x190 on Thu Mar 14, 2013 6:41 am, edited 1 time in total.
The stone age didn’t end because we ran out of stones.
---The Great Disruption - by Paul Gilding
https://paulgilding.com/
-------------------------------------------------

Frankie4Fingers
Posts: 2
Joined: Thu Mar 14, 2013 4:13 am

Re: HowTo: Bind to a specific network interface

Post by Frankie4Fingers » Thu Mar 14, 2013 4:19 am

I have been looking for ways to get this done for days, thank you for this post it was very helpful.
This post is a few years old but i'm hoping this reply will still be noticed.

I have followed all steps and have bound transmission to ethernet port 1
When i check the Message Log under debug i see "bound socket 11 to port 12345 on 10.0.1.100"
and from what i can see in IPnetMonitorX, port 12345 is indeed routing through the assigned IP.
But there are hundreds of other port numbers connecting to me it seems that all go over ethernet port 2.
When i check the Message Log again it also shows "bound socket 12 to port 12345 on :: "

What is socket 12, where did it come from and how can i bind it or delete it?

I am not sure if i bound the first one properly or if it is my routers port forwarding that is getting things done for Ethernet Port 1

(noob at this, learning as i go) Hoping someone can help me figure this out :)

Edit:
I found that by disabling Remote access i'd close the port set for that.
Now i still see two sockets but the numbers have changed to socket 9 (the one that shows it's bound, previously socket 11) and socket 10 (previously 12) that's not bound. I also disabled the NAT/port forwarding in the router and the first bind still works.

Also, as Transmission now apparently connects through 2 ports, all my torrents are counted double so some trackers are freaking out saying i am uploading duplicates etc.

x190
Posts: 5094
Joined: Sun Nov 30, 2008 4:59 am

Re: HowTo: Bind to a specific network interface

Post by x190 » Thu Mar 14, 2013 6:31 am

You haven't told us which, if any, patch you are using or whether you added bind-address-ipv4 or 6 to your settings.
bound socket 11 to port 12345 on 10.0.1.100
That is the IPv4 bind for what, I assume, is your VPN client. The actual socket number is immaterial, but usually is 11.
bound socket 12 to port 12345 on ::
That is localhost (i.e. all addresses) notation for IPv6 and you probably don't want that (if you have IPv6 connectibility) and may be what your trackers are upset about. You can stop Transmission from binding to that address in the source code or add a line in your settings.json (.plist file if Mac Client---BindAddressIPv6)---bind-address-ipv6---and set it to any non-routable IPv6 address that is not used by your VPN client.

On the other hand, if you are using thorn's patch from #2313, then you would need to add a line in your settings.json (.plist file if Mac Client---BindInterface)---bind-interface---and set it to the name of your VPN tunnel (tun/tap/ppp etc.). In that case, I think the only way to disable IPv6 would be to alter the source code or turn it off via your OS or possibly your router.

https://trac.transmissionbt.com/wiki/EditConfigFiles
But there are hundreds of other port numbers connecting to me
Each peer will have their own source port and the local destination port will be assigned by your OS. If you are trying to use a tunnel, then you do not want any Transmission traffic on eth0/1/2 etc.

Remote access is not applicable to this issue.

If you provide more info you might get a better response.
The stone age didn’t end because we ran out of stones.
---The Great Disruption - by Paul Gilding
https://paulgilding.com/
-------------------------------------------------

Frankie4Fingers
Posts: 2
Joined: Thu Mar 14, 2013 4:13 am

Re: HowTo: Bind to a specific network interface

Post by Frankie4Fingers » Fri Mar 15, 2013 1:19 am

Hi, i haven't used any patch. For some reason Safari didn't show me there were 2 pages to this thread (hence me thinking it was a few years old).
I just used the preference file editing to bind IPv4 to the IP address assigned by my router (fixed on MAC address) to Ethernet Port 2. No VPN or Proxy setup yet
as i want to get this to work first.

I just read the #2313 post and must say i don't know what i'm looking at, it is very complicated (for me).
Looks like i need to edit the .json file and bind to an interface but i thought i already did that by binding IPv4 to my ethernet port's IP, am i wrong?
EDIT: Just noticed the .patch attachments to that post, when i click on it i see a lot of code, is this something i have to copy/paste in a file somewhere or can i get a patch in the form of an installer?
Trying to learn.

I appreciate the help, if you need more details please ask i'll be happy to provide them.

x190
Posts: 5094
Joined: Sun Nov 30, 2008 4:59 am

Re: HowTo: Bind to a specific network interface

Post by x190 » Fri Mar 15, 2013 3:54 am

No VPN or Proxy setup yet
I don't understand. Transmission will just use the OS network configuration without your intervention.
The stone age didn’t end because we ran out of stones.
---The Great Disruption - by Paul Gilding
https://paulgilding.com/
-------------------------------------------------

hello_world.c
Posts: 3
Joined: Fri Mar 15, 2013 2:37 pm

Re: HowTo: Bind to a specific network interface

Post by hello_world.c » Fri Mar 15, 2013 3:13 pm

I switched to a VPN connection for torrents and had the same problem as all the other people: no stable IP address, so the bind-to-ip caused all traffic to stop. Which, with my VPN provider, tends to happen only under heavy load. Sneaky bastards...

This is the linux shell script I created, based on the fabulous two-liner from 'forty' in the trac thread:

Code: Select all

#!/bin/sh
iface="tap0"
service="transmission-daemon"
config_file="/etc/transmission-daemon/settings.json"
# test if service is currently running
if ps ax | grep -v grep | grep $service >/dev/null
then
    configured_ip=$(cat $config_file | egrep -o '\"bind-address-ipv4\": \"[^ ]*' | cut -d'"' -f4)
# test if ip has changed and is no longer available
    ping -i 1 -w 2 $configured_ip >/dev/null
    if [ $? -ne 0 ]; then
        echo ip unavailable, stop and reconfigure transmission...
        invoke-rc.d $service stop
# test if VPN went down completely
        ifconfig $iface >/dev/null
        if [ $? -ne 0 ]; then
            echo uups...$iface not available, exiting without restarting transmission...
            exit 1
        fi
# configure transmission with new ip address
        sed -i "s/\"bind-address-ipv4\":.*\$/\"bind-address-ipv4\": \"$(ifconfig $iface | egrep -o 'addr:[^ ]* ' | cut -d':' -f2 | sed 's/ //')\",/" $config_file
        service $service start
        echo transmission started.
    fi
fi
I originally tried to use this in an endless loop, just keeping the script running by starting it with '&' but it would stop working after a while. So now I use the above in a cron job I start every minute. You can easily add email or other notifications if you like. Note that I had to use 'invoke-rc.d' for stopping but 'service' for starting the daemon, don't ask me why, this may be different on your system.

Oh, the hoops we jump through in order to keep using our beloved Transmission...

Post Reply