Solving “bind: cannot assign requested address” Error When Deploying freegeoip on AWS


2 views

When migrating from Rackspace to AWS, many developers encounter the "bind: cannot assign requested address" error when trying to run network services. This specific issue with freegeoip highlights a fundamental difference between traditional hosting and AWS's elastic network architecture.

The error occurs because AWS instances have specific networking requirements:

# This will fail if the IP isn't properly assigned to the instance
$GOPATH/bin/freegeoip -addr="192.0.2.1:8080"

Unlike Rackspace where you can bind to any available IP, AWS requires:

  • The IP must be assigned to the instance's network interface
  • Security groups must allow inbound traffic
  • Network ACLs must permit the traffic

Here are three working approaches:

1. Bind to All Interfaces

The simplest solution is to bind to all available interfaces:

# Works on any interface including localhost
$GOPATH/bin/freegeoip -addr="0.0.0.0:8080"

2. Use Elastic IP Properly

If you must use a specific IP:

# First, associate the Elastic IP to your instance
aws ec2 associate-address --instance-id i-1234567890abcdef0 --public-ip 192.0.2.1

# Then verify it's attached to an interface
ip addr show

3. Check Security Configurations

Ensure proper security group rules:

# Example AWS CLI command to add inbound rule
aws ec2 authorize-security-group-ingress \
    --group-id sg-903004f8 \
    --protocol tcp \
    --port 8080 \
    --cidr 0.0.0.0/0

When the error persists:

  1. Verify interface assignment: ip addr show
  2. Check port availability: netstat -tulnp | grep 8080
  3. Test binding with Python:
    python3 -c "import socket; s = socket.socket(); s.bind(('0.0.0.0', 8080))"

For production deployments:

# Run as service with systemd
[Unit]
Description=FreeGeoIP Service
After=network.target

[Service]
ExecStart=/home/ubuntu/bin/freegeoip -addr="0.0.0.0:8080"
User=ubuntu
Restart=always

[Install]
WantedBy=multi-user.target

After migrating from Rackspace to AWS, I encountered a frustrating networking issue while deploying the freegeoip service. While the same configuration worked perfectly on Rackspace's Ubuntu servers, AWS instances (both Red Hat and Ubuntu) threw this error:

listen tcp <MY IP ADDRESS>:8080: bind: cannot assign requested address

The error occurs when the application tries to bind to a specific IP address that isn't available on the machine. In AWS environments, this typically happens because:

  • The specified IP isn't assigned to any network interface
  • The IP belongs to an Elastic IP not associated with the instance
  • Security group or NACL restrictions

First check your instance's network interfaces:

ifconfig -a
# Or for newer systems:
ip addr show

Also verify your Elastic IP assignment in AWS console or via CLI:

aws ec2 describe-addresses --public-ips <YOUR_IP>

Here are three approaches that worked in different AWS scenarios:

Solution 1: Bind to All Interfaces

Modify the freegeoip command to listen on all available interfaces:

$GOPATH/bin/freegeoip -addr="0.0.0.0:8080"

Solution 2: Use Instance Metadata

Get the actual private IP programmatically:

LOCAL_IP=$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)
$GOPATH/bin/freegeoip -addr="${LOCAL_IP}:8080"

Solution 3: Proper Elastic IP Binding

If you must use a specific public IP:

# First ensure proper NAT configuration
sudo iptables -t nat -A PREROUTING -d <ELASTIC_IP> -j DNAT --to-destination <PRIVATE_IP>
sudo iptables -A FORWARD -d <PRIVATE_IP> -j ACCEPT

# Then bind to the private IP
$GOPATH/bin/freegeoip -addr="<PRIVATE_IP>:8080"

Remember that AWS networking has some special behaviors:

  • Elastic IPs aren't directly bound to instances
  • VPC networking uses NAT for public IPs
  • Security groups must allow inbound traffic

Always verify your security group rules:

aws ec2 describe-security-groups --group-ids <YOUR_GROUP_ID>

For production deployments, consider running in a container with proper port mapping:

docker run -p 8080:8080 fiorix/freegeoip -http ":8080"

Or using systemd for better service management:

[Unit]
Description=FreeGeoIP Service
After=network.target

[Service]
ExecStart=/home/ubuntu/bin/freegeoip -http ":8080"
User=ubuntu
Restart=always

[Install]
WantedBy=multi-user.target