NAS via Ethernet on a Primarily Wireless Network
The goal here is to get a NAS talking to the Apple TV on its ethernet interface while also being accessible to the rest of your network via the ATV's wireless interface. And because USB storage is not avaliable yet, this makes for a nice alternative.
My existing setup is on 802.11g wireless which can be a little slow at times for streaming video from my NAS so I tried hooking the NAS directly up to the ethernet port. Unfortunatly, when Finder detects an ethernet connection, it seems to disable wireless!
Here's how to get ethernet and wireless to play nicely!
Setting up Ethernet and Internet Sharing
- Load up System Preferences on the ATV.
- Go to Network and configure Built-in Ethernet.
- Set it with a static IP Address on a different network segment than what your wireless connection is set to. Eg, if your Wireless interface has an IP Address of 192.168.1.2, make the Ethernet IP Address 192.168.2.2.
- Hit Apply Now to apply the changes.
- Go to Sharing and select Internet.
- Tick Built-in Ethernet. In the drop down, I expected to see Airport but it wasn't there. Set it to the blank (null) option if you can't see Airport.
- Click Start.
Network settings for the NAS
Make sure your NAS is set up with an IP address on the same segment as the ATV's Ethernet interface (eg, 192.168.2.3) and set the NAS's default gateway to the IP address you assigned to the ATV's Ethernet interface. Once you've made these changes, plug the NAS into the ethernet interface of the ATV.
Accessing the NAS from the Wireless Network
Almost done! At this point, your ATV should be able to ping the NAS via ethernet and other devices via wireless. You should also be able to mount the NAS to a directory on the ATV. However, you probably wont be able to ping the NAS from your wirelessly connected Mac which sucks because this means that you wont be able to upload anything to the NAS or administrate it.
To do this, add a static route on your Mac to tell it how to get to the NAS with a command like the following:
sudo route add -net NAS_IP_NETWORK/24 APPLE_TV_WIRELESS_IP_ADDRESS
replace NAS_IP_NETWORK with the new network you created on the ethernet side of the Apple TV and APPLE_TV_WIRELESS_IP_ADDRESS with the IP address of the ATV on the wireless side.
My NAS has an address of 192.168.2.3 and the ATV has a wireless address of 192.168.1.2, so I'd run the following command on my Mac and any other machine that needs access to the NAS (other than the ATV of course!):
sudo route add -net 192.168.2.0/24 192.168.1.2
That tells the Mac to route anything destined for 192.168.2.x to go via the wireless interface of the ATV (192.168.1.2).
You should now be able to connect to the NAS via your Mac wirelessly and mount the NAS on the ATV via direct ethernet! :)
The only minor problem I've found with this is that when the ATV is restarted with the Ethernet cable plugged in, Finder disables wireless when it starts up! To re-enable, just unplug and plug the ethernet cable back in to the ATV after boot and both will start working again.
One alternative, provided by kfinisterre on IRC:
"I noticed some people with the problem. Killing configd does not work anymore because it restarts. It is also a pain to have to boot the device with LAN unplugged. The fix is simple:"
mount -uw / cd /System/Library/SystemConfiguration/ mv KernelEventMonitor.bundle/ KernelEventMonitor.bundle_disabled reboot
I should point out that when I tested it it disabled all network services used by the AppleTV, such as streaming, youtube, movie trailers,etc. and even plugins that use the AppleTV's network code, such as ATV_Loader. Viewing files over the network with Sapphire, ATVFiles or nitoTV will still work as will syncing if iTunes is already set up to use your AppleTV. - Maraklov 22:06, 5 August 2007 (CEST)
I haven't tried this myself, but here are a couple of options for fixing this: (Note: changed a bit to use ipconfig instead of ifconfig)
- add something to rc.local- perhaps a section like this:
( sleep 60 ipconfig set en1 DHCP route ... ) &
The sleep and async subshell ("(...) &") is an attempt to avoid any weirdness due to a startup environment. Obviously you're going to have to fill in the details for the route statement. You could probably write ten lines of code to figure out what the route ought to be programatically, but I'm way too lazy. Just hard-code it, as the page author did above.
- If it's really the finder that's messing with the interfaces, that's pretty evil. It means that quitting and restarting the finder will screw up your network. In that case, you realy want a little daemon sitting around watching things and fixing them if they go bad. ISTM that all you'll need to do is two things... write a daemon like this and put it in /usr/libexec/multihome-enabler:
#!/bin/sh # Multihome-enabler # watch for a deconfigured Airport and fix it # Untested partial code - fill in the "..." # This is launched from launchd, so you might need to set up PATH while : ; do if ifconfig en1 | grep -q "inet " ; then # we're good, we have an IP address else ipconfig set en1 DHCP route... #might not be necessary? Finder may not mess with the route table fi sleep 60 done
... and write a launchd plist to get it to start:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>org.awkwardtv.multihome-enabler</string> <key>ProgramArguments</key> <array> <string>/usr/libexec/multihome-enabler</string> </array> <key>OnDemand</key> <false/> <key>ServiceDescription</key> <string>Monitor Airport, and re-enable it for multihoming if it loses its IP address</string> <key>StandardOutPath</key> <string>/dev/null</string> <key>StandardErrorPath</key> <string>/dev/null</string> </dict> </plist>
Put this plist in /Library/LaunchDaemons/multihome-enabler.plist.
Note that you'll have to set your root partition writeable to put these files in place. Don't forget to set it back to read-only afterwards.
If you're wondering why I have the 60-second sleep loop in the shell script, rather than using periodic launching by launchd... it's because I don't want to relaunch sh every minute. It'll probably never matter, though. If the other way seems cleaner to you, do that.
Also note that none of this code is tested! If you try it out, edit this to correct any mistakes, etc.