Category Archives: Networking

Dynamic DNS + tunnelbroker MikroTik script for HE.net (Hurricane Electric)

 

Note: Tested on MikroTik 6.2

/system script
add name=he-dns policy=ftp,read,write,policy,test,winbox,api source=”# Update Hurricane Electric DDNS IPv4 address\r\
\n\r\
\n#make sure previousip is initialized with a value (0.0.0.0) before the script is first run\r\
\n:global previousip\r\
\n\r\
\n:local ddnshost \”DYNAMIC_HOSTNAME\”\r\
\n:local key \”KEY\”\r\
\n:local updatehost \”dyn.dns.he.net\”\r\
\n:local WANinterface \”WAN_INTERFACE_NAME\”\r\
\n:local outputfile \”he-dns.txt\”\r\
\n\r\
\n# Internal processing below…\r\
\n# ———————————-\r\
\n:local currentip\r\
\n\r\
\n# Get WAN interface IP address\r\
\n:set currentip [/ip address get [/ip address find interface=\$WANinterface] address]\r\
\n:set currentip [:pick [:tostr \$currentip] 0 [:find [:tostr \$currentip] \”/\”]]\r\
\n:log info (\”previous ip = \”.\$previousip.\”, current ip = \”.\$currentip)\r\
\n\r\
\n:if ([:len \$currentip] = 0) do={\r\
\n :log error (\”Could not get IP for interface \” . \$WANinterface)\r\
\n :error (\”Could not get IP for interface \” . \$WANinterface)\r\
\n}\r\
\n\r\
\n:if (\$currentip != \$previousip) do={\r\
\n :log info (\”Updating DDNS IPv4 address\” . \” Client IPv4 address to new IP \” . \$currentip . \”…\”)\r\
\n\r\
\n /tool fetch mode=http user=\$ddnshost password=\$key url=\”http://\$updatehost/nic/update\\\?hostname=\$ddnshost&myip=\$currentip\” \\\r\
\ndst-path=\$outputfile\r\
\n\r\
\n :log info ([/file get \$outputfile contents])\r\
\n /file remove \$outputfile\r\
\n :set previousip \$currentip\r\
\n} else={\r\
\n :log info (\”IP has not changed, no update necessary\”)\r\
\n}”
add name=he-tunnelbroker policy=ftp,read,write,policy,test,winbox,api source=”# Update Hurricane Electric tunnelbroker IPv4 address\r\
\n\r\
\n#make sure previousip is initialized with a value (0.0.0.0) before the script is first run\r\
\n:global previousip\r\
\n\r\
\n:local tunnelid \”TUNNEL_ID\”\r\
\n:local tunnelinterface \”TUN_INTERFACE_NAME\”\r\
\n:local user \”USERNAME_TUNNELBROKER\”\r\
\n:local pass \”PASSWORD_TUNNELBROKER\”\r\
\n:local updatehost \”ipv4.tunnelbroker.net\”\r\
\n:local WANinterface \”WAN_INTERFACE_NAME\”\r\
\n:local outputfile \”he-tunnelbroker.txt\”\r\
\n\r\
\n# Internal processing below…\r\
\n# ———————————-\r\
\n:local currentip\r\
\n\r\
\n# Get WAN interface IP address\r\
\n:set currentip [/ip address get [/ip address find interface=\$WANinterface] address]\r\
\n:set currentip [:pick [:tostr \$currentip] 0 [:find [:tostr \$currentip] \”/\”]]\r\
\n:log info (\”previous ip = \”.\$previousip.\”, current ip = \”.\$currentip)\r\
\n\r\
\n:if ([:len \$currentip] = 0) do={\r\
\n :log error (\”Could not get IP for interface \” . \$WANinterface)\r\
\n :error (\”Could not get IP for interface \” . \$WANinterface)\r\
\n}\r\
\n\r\
\n:if (\$currentip != \$previousip) do={\r\
\n :log info (\”Updating tunnelbroker client IPv4 address to new IP \” . \$currentip . \”…\”)\r\
\n\r\
\n /tool fetch mode=https user=\$user password=\$pass url=\”https://\$updatehost/nic/update\\\?hostname=\$tunnelid&myip=\$currentip\” \\\r\
\ndst-path=\$outputfile\r\
\n\r\
\n /interface 6to4 set \$tunnelinterface local-address=\$currentip\r\
\n\r\
\n :log info ([/file get \$outputfile contents])\r\
\n /file remove \$outputfile\r\
\n :set previousip \$currentip\r\
\n} else={\r\
\n :log info (\”IP has not changed, no update necessary\”)\r\
\n}”

Initialize previousip with the following command in the Terminal:

:global previous “0.0.0.0”

References:

Recipient MX-based dnslookup routing for cPanel’s Exim

I host a few websites and emails for my friends and relatives on my cPanel server.  I need to ensure that their emails don’t end up in Spam/Junk folder when they send to email addresses hosted on Google/Yahoo/Hotmail (common problem with small webhosting companies).  I can easily forward/relay every single remote delivery via an ESP’s smarthost, but that would be too costly for me since ESPs charge by the amount of emails relayed.  Getting certified by ReturnPath is also expensive and takes some time.  I just need at least the major ones to be relayed, so I needed a recipient MX-based routing for my Exim.  It doesn’t look proper, but it works great!  I’m sure many small cPanel hosts will face this similar problem.

authenticators:

esp_relay_login:
driver = plaintext
public_name = LOGIN
client_send = : ${extract{user}{${lookup{${lookup{$sender_address_domain}lsearch*{/etc/mail_relay_mapping}{$value}}}lsearch{/etc/mail_relay_secret}{$value}}}} : ${extract{pass}{${lookup{${lookup{$sender_address_domain}lsearch*{/etc/mail_relay_mapping}{$value}}}lsearch{/etc/mail_relay_secret}{$value}}}}

routers:

smarthost_dkim:
driver = dnslookup
domains = !+local_domains : ! /etc/mail_domain_excluded_from_using_relay
require_files = “+/var/cpanel/domain_keys/private/${sender_address_domain}”
transport = remote_smtp_smart_dkim
ignore_target_hosts = ! /etc/mail_ips_of_domains_to_be_relayed
senders = ! /etc/mail_exclude_from_relay

smarthost_regular:
driver = dnslookup
domains = !+local_domains : ! /etc/mail_domain_excluded_from_using_relay
transport = remote_smtp_smart_regular
ignore_target_hosts = ! /etc/mail_ips_of_domains_to_be_relayed
senders = ! /etc/mail_exclude_from_relay

transports:

remote_smtp_smart_dkim:
driver = smtp
hosts_require_tls = *
interface = ${if exists {/etc/mailips}{${lookup{$original_domain}lsearch{/etc/mailips}{$value}{${lookup{$sender_address_domain}lsearch{/etc/mailips}{$value}{${lookup{${perl{get_sender_from_uid}}}lsearch*{/etc/mailips}{$value}{}}}}}}}}
helo_data = ${if exists {/etc/mailhelo}{${lookup{$original_domain}lsearch{/etc/mailhelo}{$value}{${lookup{$sender_address_domain}lsearch{/etc/mailhelo}{$value}{${lookup{${perl{get_sender_from_uid}}}lsearch*{/etc/mailhelo}{$value}{$primary_hostname}}}}}}}{$primary_hostname}}
dkim_domain = $sender_address_domain
dkim_selector = default
dkim_private_key = “/var/cpanel/domain_keys/private/${dkim_domain}”
dkim_canon = relaxed
hosts_require_auth = *
hosts = ${lookup{$sender_address_domain}lsearch*{/etc/mail_relay_mapping}{$value}}::587
hosts_override = yes

remote_smtp_smart_regular:
driver = smtp
hosts_require_tls = *
interface = ${if exists {/etc/mailips}{${lookup{$original_domain}lsearch{/etc/mailips}{$value}{${lookup{$sender_address_domain}lsearch*{/etc/mailips}{$value}{${lookup{${perl{get_sender_from_uid}}}lsearch*{/etc/mailips}{$value}{}}}}}}}}
helo_data = ${if exists {/etc/mailhelo}{${lookup{$original_domain}lsearch{/etc/mailhelo}{$value}{${lookup{$sender_address_domain}lsearch{/etc/mailhelo}{$value}{${lookup{${perl{get_sender_from_uid}}}lsearch*{/etc/mailhelo}{$value}{$primary_hostname}}}}}}}{$primary_hostname}}
hosts_require_auth = *
hosts = ${lookup{$sender_address_domain}lsearch*{/etc/mail_relay_mapping}{$value}}::587
hosts_override = yes

 

Files needed:

/etc/mail_domain_excluded_from_using_relay: (exclude emails sent to these domains from being relayed to smarthost)
abc.com
cde.com

/etc/mail_exclude_from_relay: (exclude emails sent from these domains from being relayed to smarthost, this should be your customers’ domains hosted on your server)
def.com
ghi.com
jkl.com
mno.com

/etc/mail_ips_of_domains_to_be_relayed: (MX IPs of domains which Exim will relay via smarthost)
#Google
74.125.0.0/16
173.194.0.0/16
#Hotmail
65.52.0.0/14
#Yahoo APAC
106.10.128.0/18
#Yahoo EU
188.125.64.0/21
#Yahoo US
68.180.128.0/17
98.136.0.0/14
66.196.64.0/18
63.250.192.0/19

/etc/mail_relay_secret: (list of credentials for smarthosts, list down all smarthosts that you will use in /etc/mail_relay_mapping below)
smtp.example.com: user=postusername pass=password
smtp.example.net: user=postuser pass=pass123
smtp.example.org: user=boo pass=hoo

/etc/mail_relay_mapping: (list of domains to explicitly map to certain smarthost, last entry is default smarthost)
ghi.com: smtp.example.org
def.com: smtp.example.net
jkl: smtp.example.org
*: smtp.example.com

Thus if mno.com sends an email to Gmail/Hotmail/Yahoo, it will be relayed via smtp.example.com.

How do you check if it works?  Test by sending an email to certain domain like Yahoo and watch Exim’s log.  For domains that should be relayed, it should say remote_smtp_smart_regular or remote_smtp_smart_dkim transport (T) in the logs:

1VFjpE-0002oA-Tb => xxxxx@yahoo.com R=smarthost_regular T=remote_smtp_smart_regular H=smtp.example.com [123.123.123.123] X=TLSv1:DHE-RSA-AES256-SHA:256
1VFjFr-0007hX-QJ => xxxxx@gmail.com R=smarthost_dkim T=remote_smtp_smart_dkim H=smtp.example.org [124.124.124.124] X=TLSv1:DHE-RSA-AES256-SHA:256

Normal route would be remote_smtp or dkim_remote_smtp:

1VDN3n-00088z-46 => yyyyy@gmail.com R=lookuphost T=remote_smtp H=gmail-smtp-in.l.google.com [173.194.79.26] X=TLSv1:RC4-SHA:128
1VDWNC-0002Zo-OB => zzzzzz@hotmail.com R=dkim_lookuphost T=dkim_remote_smtp H=mx2.hotmail.com [65.55.92.152]

Thanks to Chris Siebenmann!

References:
http://www.gossamer-threads.com/lists/exim/users/97299
http://www.tgunkel.de/docs/exim_smarthosts.en

Noteworthy links:
http://serverfault.com/questions/347285/exim-redirect-to-smart-host-based-on-mx-record
http://www.gossamer-threads.com/lists/exim/users/97056

Issues with NTP

If you wonder why your VPS or specifically OpenVZ VE’s ntpd is stuck at stratum 16 or stratum 0 while ntpq -p shows no abnormality (use ntpq -c rv to check state, it should say state=3 when abnormal), then try executing ntpdate manually. If it says “ntpdate: step-systime: Operation not permitted”, then you need to reconfigure your OpenVZ VE or ask your host to do it for you: vzctl set 123 –capability sys_time:on –save

If everything is fine but this message “ntpdate: no server suitable for synchronization found” keeps coming up, then it could be your ISP blocking UDP port 123. Use ntpdate -u to verify, this option should circumvent the firewall.

References:
http://blog.haite.ch/2009/05/22/1242984900000.html

iptables mangle and NAT notes, etc.

PREROUTING in nat table: DNAT, REDIRECT
POSTROUTING in nat table: SNAT/MASQUERADE

PREROUTING in mangle table: alter routing (e.g. source-based routing)
FORWARD in mangle table: traffic shaping for tc (flowid)

In MikroTik RouterOS, /ip firewall nat:
srcnat chain = PREROUTING
dstnat chain = POSTROUTING

/ip firewall mangle:
prerouting chain = global-in
forward chain = global-out (support NAT traffic shaping, higher load on router)

Update: I used to think that global-in literally means global input, while global-out literally means global output.  Apparently I was mistaken.  The parent queues MUST be matched to the right parent, either global-in, global-out, global-total, or one of the network interfaces depending on the mangle rules.  Top-most queue parent (global-in, global-out, global-total) doesn’t decide whether it’s up/down.  The mangle rules do the direction decision trick, whether a packet is incoming/download or outgoing/upload.  This makes perfect sense now! (doh)  I kept wondering why half of my queues (download queues’ top-most parent was global-in) weren’t working, when all my mangle rules were in forward chain.  Obviously they wouldn’t, because global-in marks both direction in prerouting chain.

Update 2: mangle: download rules first then upload rules. global-in, connection mark: prerouting; packet mark: prerouting. global-out, connection mark: forward, packet mark: postrouting.

 

This didn’t make sense until I read the URL listed below under References.  Silly me!  Assumption is the root of most, if not all, problems indeed.

References:
http://wiki.ispadmin.eu/index.php/Documentation/Mikrotik_guide#.22Global-in.22_vs._.22global-out.22_setup

Extending PPPoE access network with network bridge

In a situation, I had to extend my PPPoE network over a wireless bridge. I do not want to have nor maintain 2 PPPoE servers. I didn’t bother failed to understand how PPPoE works and made a wireless bridge without WDS. When one user log in from the bridged side of the network, it works flawlessly. When more users are trying to log in, the user which logged in earlier gets disconnected. Apparently this is caused by MAC address problem[1]. From the PPPoE server’s side, users logging in from the bridged side of the network have the same MAC address which is the bridge device’s MAC address. From the users’ side, they are able to see correct MAC address of every device on the other side of the network. The PPPoE server gets confused when it sends PPPoE packets because multiple users have the same MAC address and there is no way for the server to direct reply to individual user.

[1]Wireless AP is connected to the side of the network where the PPPoE server is connected to, and wireless client is connected to the other side of the network. Every device connected to the same side of the wireless AP gets the wireless client’s MAC address for every device connected over the wireless bridge, however every device over the bridge gets to see the real MAC address of every device connected to the same side of the wireless AP. I believe that if I interchange the wireless AP and client (so now PPPoE server is connected to the wireless client instead), it may work properly since the PPPoE server will get the correct MAC address of all devices over the bridge. Devices connected to the wireless AP obviously will get the same MAC address for the PPPoE server and PPPoE users connected to the same side of the wireless client, but the most important thing is that the PPPoE users over the bridge can communicate properly with the PPPoE server. Since this is a one-to-many and many-to-one situation, this should work, but not for many-to-many situation. This explanation sounds quite confusing due to my limited English. If you could rewrite this part, please let me know.

krb5-telnet != telnet-server

I had a task to allow root login via telnet on RHEL 4.3 servers. I tried my luck on Google and found this. Once I have done exactly as mentioned, I still couldn’t login as root via telnet.

After researching a little bit more on Google, I finally found the answer! Apparently krb5-workstation‘s /etc/xinetd.d/krb5-telnet is not the telnet-server package that I have been looking for. telnet-server‘s telnetd is actually another package which is mentioned in the document I found earlier. I disabled krb5-telnet and enabled telnet in /etc/xinetd.d/.

Voila! Now it allows root login via telnet. Red Hat should have written a note about this in the document.

PS: Please enable telnet-server ONLY if you need it and you know what you’re doing. I do NOT recommend the use of telnet-server.

References:
http://kbase.redhat.com/faq/FAQ_45_453.shtm
http://forums11.itrc.hp.com/service/forums/questionanswer.do?admit=109447626+1210184407758+28353475&threadId=1035531

MikroTik RouterOS Interface Bonding

I have two separate Metro Ethernet links (via fiber optic) from the datacenter to the NOC. Each link is 10Mbps. I need to utilize both links (bonding) and make sure sure that if one of the links goes down (redundancy), I won’t lose half of my packets. Bonding and redundancy are my goals.

Initially I tried Cisco Catalyst’s EtherChannel feature to accommodate this need since I learned about EtherChannel when I was doing my CNAP. Unfortunately EtherChannel cannot fit in this scenario due to my Metro Ethernet provider’s network setup. They use Cisco Catalyst 3750 switches to aggregate customers links from each POP to their headquarters. My first attempt was to establish trunk mode EtherChannel (802.1q) with Cisco Catalyst 2950 on one side and Cisco Catalyst Express 500 on the other side. Later I noticed that this is not doable since trunking requires MTU size to be larger than 1500 (1504) when my provider strictly limits MTU size to 1500 and negotiation between my 2 switches to establish trunking wouldn’t work since my switches’ BPDU packets are “intercepted” by my provider’s switches. Basically my Cisco switches were trying to establish a VLAN trunk with my provider’s directly connected switches when my switches are  supposed to be negotiating to each other.

I consulted a few experienced people including an employee of the provider, and they told me to use access mode EtherChannel instead of the trunk mode EtherChannel. This is not possible with Cisco Catalyst Express 500, which only offers trunk mode EtherChannel. I bought a Cisco Catalyst 2960 to replace the Cisco Catalyst Express 500 hoping that access mode EtherChannel would work, it didn’t. Even if it did work, it wouldn’t be aware of link state changes since my switches do not connect directly to the fiber cables. There is a fiber-to-ethernet bridge for each side of each link, so my switches will always detect both links as always up as long as the bridges are up.

Since link states cannot be used as a measurement in this scenario, I had to find another way. MikroTik RouterOS offers not only bonding feature, but fail-over mechanism too! The fail-over mechanism uses ARP packets to detect link failures, it is far from perfect but at least it works.

I will add examples later, but for now have a look at this. Hopefully I will discuss EoIP and EoIP over PPTP too.

References:
http://www.mikrotik.com/testdocs/ros/3.0/interface/bonding.php

RP-PPPoE server problem in Fedora Core 5, 6, Fedora 7, 8

Since Fedora Core 5, pppoe-server that comes with rp-pppoe RPM package has always been broken. Someone actually filed a bug report, but unfortunately there was no response. Apparently the problem is caused by ppp conflicting with syslogd. If you stop syslogd and klogd, then pppoe-server will run properly. Fedora Core 4 does not have this problem though. I’m not sure if the newly released Fedora 7 has got this issue sorted out. I’m guessing that they haven’t.

If you have installed Fedora 7 and found out that the issue has been fixed, please let me know ASAP. Thanks! 🙂

Update (Jul 03, 2007): Problem confirmed in Fedora 7.

Update (Mar 14, 2008): Problem fixed as stated on bugzilla ticket.

PPPoE Server HOWTO for MikroTik RouterOS 2.9

If you wish to run a PPPoE server, MikroTik RouterOS provides a convenient way to set one up in a few minutes (with built-in traffic shaping feature too!). Previously I used Fedora Core for my PPPoE servers, but I couldn’t find a working solution to keep ghost PPPoE sessions from bogging down my Linux server. I tried MikroTik DOM with RouterOS to replace my Linux-powered PPPoE servers, so far the results are very good.

Below is a mini guide that may be able to help you get your PPPoE server running in a few minutes using RouterOS.

First, make sure that your RouterOS server’s WAN connectivity has been properly configured. Remember that you need at least 2 network interface cards (NICs). This guide assumes that both NICs are ethernet — ether1 and ether2. If you haven’t set anything up on the new system, let me help you with the checklist: (based on my experience, the following issues are the most common)

  • Make sure that the Internet-facing NIC has an IP address assigned on it and the default gateway is set (/ip route add gateway=…)
  • If NAT is used, ensure that src-nat/masquerade firewall rule has been added (/ip firewall nat …) and it is working properly

Once you have verified the server’s connectivity, create a PPP profile (/ppp profile add name=”pppoe-profile” local-address=10.1.1.1 dns-server=… rate-limit=128k/128k). Every user account that uses this profile will get 128Kbps upload and download limit. If you wish to have different types of accounts (for example some customers pay for 256Kbps), create a new PPP profile (change the rate-limit attribute).

Next, create a user account assigned to the new PPP profile (/ppp secret add name=”andryan” password=”test” service=pppoe profile=”pppoe-profile” remote-address=10.1.1.2). When this user logs in successfully, this user gets assigned 10.1.1.2. To dynamically assign IP addresses, there is an example here.

Finally, create a PPPoE server instance (/interface pppoe-server server add service-name=”pppoe1″ interface=ether2 one-session-per-host=yes default-profile=”pppoe-profile”) and enable it. Now your RouterOS PPPoE server is ready to answer PPPoE requests and authenticate your PPPoE clients. 🙂

Good luck!

References:
http://www.mikrotik.com/testdocs/ros/2.9/interface/pppoe.php