Linux Wan Load Balancing

Comment

Linux Network

Merhaba
Internet artık hayatımızın olmazsa olmazı. Şirketler için ise işlerin yürümesi için en temel ihtiyaç.
Bu bağlamda küçük bir çalışma yaptım ve sizlerle paylaşıyorum. ( 3 hafta sürdü 🙂 )

GitHub Link

Sorun:
1- Internet altyapısı, limitli paketler, düşük hızlar ve yüksek fiyatlar dolayısı ile internet verimli kullanılamıyor.
Herkes metro/fiber gibi internet hatlarını pahalı olması sebebi ile alamıyor veya altyapı desteklemiyor.

2- Fiber/metro hat kullansanız bile belediyeci abiler veya doğalgazcı abiler kepçe’yi koyduğu gibi hattı koparıyor.
Dalayısı ile sizin yedek bir hatta ihtiyacınız oluyor.
Yedek hat bazen ADSl bazen Radio Link Bazen de 3G/4G olabiliyor.

Çözüm:
Bu sorunu çözmek için birden fazla adsl/vdsl satın alınıp (ucuz olması nedeni ile), bunlara toplam trafik paylaştırılarak internet daha verimli kullanılabilir.
Linux üzerinde Internet hatları için yük dengeleme ve failover yapabilen ufak bir kod yazdım.
Bu süreçte linux üzerinde bir sürü sorun ile karşılaştım. Çoğunu çözdüğümü düşünüyorum. 🙂 Yazının içerisinde bu sorunlara değineceğim.

Ne gerek var. “Parasını verip bu işi yapan ürün alırım” – derseniz sonrasını okumanıza gerek yok. 🙂

Geri Bildirim: Sorunları mesaj olarak yazabilirsiniz. Elimden geldiğince düzeltmeye çalışırım.

Lisans: GPL3

Gereksinimler:

1- Linux dağıtımı (Ubuntu/Debian/Centos/RedHat)
2- iptables/netfilter ve statistic modülü
3- iproute2 (Hemen her linux dağıtımında öntanımlı gelir.) Önemli olan dummy ethernet desteğinin olmasıdır.
Komut satırında bunu çalıştırarak görebilirsiniz.
# ip link help”
TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can }
4- bc komutu (yum install bc -y veya apt-get install bc -y)
5- ping ( Bu kesin vardır. )

Ek olarak aşağıdakiler olsa iyi olur.
1- “dnsmasq” Buradan faydalanabilirsiniz. (Sistem DNS önbellek desteklemelidir. Aksi durumda Linux router’inizin kendisinde isim çözme işlemleri yavaş olmaktadır.)
2- “host” komutu (bind-utils paketi ile gelir isim sorgulama testi için kullanılır.))

Ön Bilgi:
Ben testlerimi Centos üzerinde yaptım. Debian/ubuntu üzerinde de bir farklılık olacağını düşünmüyorum.
Tek fark var o da startup ayarları. Şuanki hali Centos 5 ve 6 üzerinde init script’i ile çalışıyor.
Centos üzerinde chkconfig ile startup için ayarlar hazır geliyor. Ubuntu için ayrıca bakmak gerekiyor. Belki ileride ubuntu/debian için eklerim. 🙂
Eğer systemd (centos7/redhat7/debian8) kullanıyorsa sisteminiz Startup ayarlarına ayrıca bakmalısınız. Belki ileride bunu da eklerim. 🙂

Ön Hazırlık:
Linux router’inizde en az 3 ethernet bulunmalıdır. IP adresleri tanımlanmalıdır. Önemli olan cihaz yeniden açıldığında bu ip adreslerini yeniden almalıdır. Yani kaydetmelisiniz.
Ben burada 3 tane internet hattının olduğunu varsayarak toplamda 4 etherneti olan bir sistem kullanacağım.

CentOS/RedHat/Fedora üzerinde IP ayarları (ubuntu/debian için internetten yardım alabilirsiniz :))

/etc/sysconfig/network-scripts/ifcfg-eth0

/etc/sysconfig/network-scripts/ifcfg-eth1

/etc/sysconfig/network-scripts/ifcfg-eth2

/etc/sysconfig/network-scripts/ifcfg-eth3

Network Servisini yeniden başlatıp IP adreslerini almasını sağlıyoruz. (Centos7’de servis yönetimi farklı. Internetden bakabilirsiniz.)

IP adreslerini kontrol edelim.

Buraya kadar herşey tamam ise kuruluma geçebiliriz.

Kurulum:

git uygulaması yüklenir.

Wan load balance paketi indirilir.

İndirilen klasöre girilir.

Kurulum scripti çalıştırılır. (öncesinde ihtiyaç olur ise “chmod +x setup”)

Daha sonra kaldırmak isterseniz. (öncesinde ihtiyaç olur ise "chmod +x setup")

Ayarlar:
Tek tek her parametrenin ne anlama geldiğine bakalım.

wan_load_balancing_enable
Wan load balancing’i açıp kapatmak için kullanılır. Ön tanımlı açıktır.

ip_forward
Seçeneği ile Linux Sistemimizin router olarak çalışacağını belirtiyoruz. Zorunlu olarak “y” yani açık olmalıdır.
Eğer başka bir uygulamanız bu işlemi yapıyor ise o zaman “n” olabilir.

disable_rp_filter
Seçeneği açık olmalıdır. Aksi halde paketler internete gider cevabı iç bacağa geçmez.
Ön tanımlı açık durumdadır. Servis başlarken mevcut ayarlarınızı kaydedip daha sonra servis durdurulurken geri yükler.

sticky_inbound_wan_connections
Seçeneği aktif edildiğinde internette açık servisleriniz için hangi internet hattından trafik geliyor ise yine aynı yere geri döner.

Örn. Dışarıya açık web sunucunuz var ve 80 portunu içerideki bu sunucuya yönlendirdiniz.
Normal şartlarda 3 internet hattınız var ise istek 1 nolu internet hattından gelip cevap 2 nolu internet hattından geri dönebilir. Çünkü Wan Load balancing servisleri dışarı doğru toplam trafiği ağırlıkları oranında bölerek yollarlar. O anda hangi internet hattına denk gelirse cevabı da oraya yollayacaktır.
Bu durumda dışarıdan erişim kurulamaz. Bu durumun önüne geçmek için bu seçenek aktif edilir.

Bu seçenek aynı zamanda şunu da sağlamış olacak.
Dışarıya açık mail sunucunuz veya web sunucunuz var. DNS kayıtlarındaki ttl sürelerine bağlı olarak hatlardan birisi gitse bile diğerleri üzerinden servisler çalışmaya devam edecektir.
Yani 3 tane internet hattınız var ise 3’üne de gelen 80 ve 25 portlarını tek bir suncuya yönlendirdiğinizde istekler hangi hattan geliyor ise cevaplar oraya dönecektir.
Herhangi bir sorun olmadan çalışacaktır.

Ön tanımlı açık olarak gelir. Açık olması önerilir.

Rule Priority Settings
sticky_conn_rule_no
Iptables PREROUTING Zinciri Kural sıralamasını buraya yazacağınız kural numarasına göre ayarlar.
Ön tanımlı olarak Zincirin en üstüne eklenir.

wlb_pre_rule_no
Iptables PREROUTING Zinciri Kural sıralamasını buraya yazacağınız kural numarasına göre ayarlar.
Ön tanımlı olarak en üsttedir. Eğer sticky_inbound_wan_connections=”y” bu seçenek aktif ise ön tanımlı olarak Kural numarası 2 olarak ayarlanır.
Eğer sticky_conn_rule_no=”” bu seçenekte kural numarasında bir değişiklik yaparsanız. wlb_pre_rule_no seçeneğindeki kural numarası sticky_conn_rule_no seçeneğindeki kural numarasından 1 fazla olmalıdır.
Örn:
sticky_conn_rule_no=”5″
wlb_pre_rule_no=”6″

wlb_out_rule_no
Iptables OUTPUT Zinciri Kural sıralamasını buraya yazacağınız kural numarasına göre ayarlar.
Ön tanımlı en Iptables OUTPUT zincirinin En üstüne eklenir.
Linux Router’inizin kendinden çıkan trafik Wan Load Balance’e girmesi için eklenir.

wlb_snat_rule_no
Iptables POSTROUTING Zinciri Kural sıralamasını buraya yazacağınız kural numarasına göre ayarlar.
Ön tanımlı olarak en sona eklenir. Bu sayede mevcut SNAT kurallarınız çalışmaya devam eder.

wlb_raw_pre_rule_no
Iptables raw tablosu PREROUTING Zinciri Kural sıralamasını buraya yazacağınız kural numarasına göre ayarlar.
Ön tanımlı olarak en üste eklenir.

wlb_raw_out_rule_no
Iptables raw tablosu OUTPUT Zinciri Kural sıralamasını buraya yazacağınız kural numarasına göre ayarlar.
Ön tanımlı olarak en üste eklenir.

Wan Link Settings
Her internet hattı sırası ile yukarıdan aşağıya doğru ilgili değerler doldurularak tanımlanır.
Örn;

route_table_ids
IPRoute2 tablo numarası. Her internet hattı için farklı bir tanım yapılır. Daha önce kullanılan ID ile ile aynı olmamasına dikkat edilir.
fwmarks
Netfilter/Iptables işaret numrası. Bu numaraya göre IPTables Kuralları oluşturulur. Her internet hattı için farklı olmalıdır. Daha önce kullanılan bir mark var ise aynı olmamasına dikkat edilir.
wan_ifaces
Internet Hattının takılı olduğu ethernet adı.
wan_iface_ips
Internet hatlarının takılı olduğu ethernet’in IP adresi.
routers
Yönlendirici IP adresi, yani internet hattının bulunduğu cihazın IP adresi.
weights
Her internet hattı için yük oranı değeri yazılır. Bütün hatlara eşit dağıtılacak ise hepsine “1” yazılır.
Weight Hesaplaması şu şekilde yapılır.
weight= (1 / (toplam_agirlik – kullanılan_agirlik) * hat_agirligi)
Örneğe bakacak olursak.

weights=” 5 3 2 ”
toplam_agirlik= 5+3+2=10

Hat 1
kullanilan_agirlik=0

Hat 2
kullanilan_agirlik=5

Hat 3
kullanilan_agirlik=5+3=8

Burada biraz karışmış gibi gözükebilir. Açıklamaya çalışayım.
Toplam 100 bağlantı olduğunu düşünelim. Bunları 3 farklı internet hattına dağıtmak istediğimizde sistem şöyle çalışır.
Kural1:
%50’sini Hat1’e gönder. Burada sorun yok. 50 Bağlantı hat1’e yönlendirilecek.
Kural2:
Burada %30’unu hat2’ye yolla dersek yanlış olur. Burada 100 bağlantı değil, kural1 %50’sini hat1’e gönderdiği için geriye 50 bağlantı kalıyor.
50’nin %30’u 15’dir. Bu durumda Hat2’nin ağırlığı 3 olmasına rağmen 15 bağlantı yönlendirilmiş olur. Hat3’ün ağırılığı 2 olmasına rağmen daha fazla bağlantı işlemek zorunda kalır.
Çözümü için Hat1’e dağıtılan ağırlık hat2 hesaplanırken toplamdan çıkartılarak ağırlık hesaplanır.
Hat2 için %60 gibi bir oran gözüksede, kalan 50 bağlantıdan hat2’ye 30 bağlantı yönlendirilir. Yani 100 bağlantının %30’una denk gelir.
Kural3:
Kural2’de yapılan hesaplamanın aynısı burası içinde geçerlidir. Burada ek olarak Hat1 ve Hat2 ağırlıkları toplamdan çıkartılarak hesaplama yapılır.(Hat sayısına göre bu durum artarak devam eder.) Hat3 için sonuç %100 gözükse bile aslında kural1 ve kural2’den geriye kalan 20 bağlantının tamamı anlamına gelir.

Son durumda aşağıdaki şekilde yükü hatlara dağıtmış olduk.
Hat1: 50
Hat2: 30
Hat3: 20

dummy_iface_ip
Yazının başında Linux daki bazı sorunlardan bahsetmiştim. Bunların başıdan da bu seçenek ile çözüme ulaştırdığım sorunlar var.
Linux 3.6 kernel sonrasında routing cache özelliği silindi. Bu özellik silindiği için internette bir çok yerde bahsedilen load balancing dökümanlarının her biri geçerliliğini yitirdi.
Bir çok döküman nexthop tanımları ile wan link load balancing yaptırıyor. Ancak bu yöntem tamamen routing cache makanizması üzerinde çalışıyordu.
Bu özellik kernel’den silindiği için artık çalışmaz oldu. Sebep, Performans sorunları. İlginç olan bu özelliğin yerine herhangi bir yenilik getirmemiş olmaları.
Tabi bu durum bir çok sorunu beraberinde getirdi.
1- Routing cache silindiği için Linux Router’inizin kendi trafiği load balance’e girdiğinde özellikle icmp paketleri siz ping testi yapmaya devam ederken 2 ping testinden sonra otomatik olarak diğer hatlara geçiyor. (nexthop kullanıldığı durumda)
2- İstemci bilgisayarların TCP bağlantıları düzgün kurulmamaya başladı. Çünkü routing cache silindiği için ilk paket ISP1 den gidiyor aynı oturumun ikinci yada üçüncü paketi ISP2 den gidiyor. Bu durumda oturum kurulamıyor. (tcp 3’lü el sıkışma) Bazen oturum kurulduktan sonra diğer hatta gidiyor.
Örn: SSH bağlantısı kurarken kullanıcı adını girdikten sonra şifreyi sorduğu kısımda bağlantı diğer internet hattına geçiyor hali ile oturum düşüyordu.

Diğer sorunlar;
Bu özelliği kullanmayıp sistemde tek bir hattı default router olarak girebilirsiniz ancak Linux Router’inizin kendinden internete çıkan trafik o hat gittiği zaman çalışmayacaktır.

Normalde benim yaptığım script’i kullandığınızda Linux router’inize herhangi bir öntanımlı ağ geçidi tanımlamasanızda load balance kullandığınız için internete çıkmaya çalışır. Ancak sorun iptables’a paket girince lokal işlemler kısmından çıkamıyor. Buradan çıkabilmesi için muhakkak bir ön tanımlı ağ geçidine ihtiyaç duyuyor.
Ayrıca Benim yaptığım 🙂 bu script ile Linux Router’inizde ön tanımlı ağ geçidi olmasa da arkasındaki istemci bilgisayarlarda herhangi bir sorun olmadan Load balance olur ve internetleri çalışır.

Neden Linux router’imizin ön tanımlı ağ geçidine ihtiyaçı var.
Bunun cevabı basit aslında. Genellikle Linux Routerler tek bir iş için kullanılmaz. squid, postfix vs. bir çok servis vardır. Bu servislerin çalışabilmesi için gereklidir.
En başta ise DNS ihtiyacı gelir. Linux Router’imiz ön tanımlı ağ geçidi olmadığı için yani kendisi internete çıkamadığı için isim çözemeyecek ve üzerinde çalışan diğer servisler çalışmayacaktır.

Velhasıl bir sürü deneme ve araştırmadan sonra bir çözüm yolu buldum.

Çözüm:
iproute2 paketi ile birlikte gelen ve yazının en başında da gereksinimler kısmında söylediğim gibi dummy interface desteğinin olmasıdır.
dummy interface oluşturup default router olarak bu interface’i yazınca yukarıda bahsettiğim bütün sorunlarımız çözülüyor.
Ancak burada da şöyle bir sorun oldu. Centos7 üzerindeki testlerimde interface’e IP vermeyince çalışmadı. Bu yüzden bende ön tanımlı olarak IP adresi vermenin bir zararı olmadığını düşünerek bu fonksiyonu ekledim.

Bu nedenle dummy interface IP adresini aşağıda istediğiniz bir ip adresi olarak belirtebilirsiniz.
ön tanımlı 1.1.1.1 olarak gelir ve /32 olacak şekilde eklenir.
dummy interface adı sistemde wlb0 olarak gözükür.

dead_router_detection
Çalışmayan internet hatlarını tespit edip otomatik olarak kurallardan kaldırır. Bu sayade çalışmayan internet hattına paket girmez ve kayıp olmaz.

failure_count
Toplam hata sayısı. Ping testi ile toplam hata sayısı belirlenen değere ulaşırsa hattın gittiğini düşünecek ve kuralları silecektir.

success_count
Toplam doğru test sayısı. Pink testi ile giden hattın tekrar geri geldiğinde kaç başarılı ping testinden sonra hattın geldiğini anlayıp kurallarını yeniden eklesin.

sleep_time
Test tekrar süresi. Testi kaç saniye aralıklarlar tekrarlasın.

test_hosts
Ping testi yapılacak IP adresleri. Boşluk bırakılarak birden fazla yazılabilir.
Burada önemli olan her ping adresi başarılı veya baraşırız sonuç demektir.
Yani aşağıdaki örnekte 2 tane test adresi var. ISP1 üzerinde bu 2 IP adresine ping testi sonucu başarısız olur ise failure_count 2 olur. Bir sonraki tekrarda aynı şekilde başarısız olur ise toplamda 4 başarısız işlem olur ve bu internet hattının çalışmadığını düşünür. (failure_count 4 ise.)
Tam tersi yine başarılı olduğu durum için geçerlidir. Ek olarak succes_count sayısı kadar başarılı olduğu durumda failure_count 0 olur.

Ping Test Settings
interval
Kaç mili saniye aralıklar ile ping atılacak.

timeout
Ping isteğinin cevabı ne kadar süre beklenecek.

count
Her test IP adresine kaç adet ping atılacak.

Link Kontrol
Sistem ön tanımlı olarak Ethernet üzerinde kablo takılı değilse veya ethernet elle kapatıldıysa o hattı yok sayar ve kurallarını siler.
Geri geldiğinde otomatik olarak ekler.

Ayar dosyası
/etc/sysconfig/wan-load-balance/wlb.conf

Bütün yapılandırma yapıldıktan sonra servis başlatılır.

Her şey yolunda gitti ise artık bir wan link load balancer’iniz oldu.

🙂

Referans:

  • http://pof.eslack.org/2011/02/04/generic-load-balancer-for-multiple-wan-links/
  • http://www.sysresccd.org/Sysresccd-Networking-EN-Iptables-and-netfilter-load-balancing-using-connmark
  • https://home.regit.org/netfilter-en/links-load-balancing/
  • http://parkersamp.com/2010/03/howto-using-linux-as-a-simple-load-balancer-nat-router-firewall/
  • http://vyos.net/wiki/How_to_make_inbound_WAN_connections_sticky_to_the_interface
  • http://blog.khax.net/2009/12/01/multi-gateway-balancing-with-iptables/
  • http://blog.khax.net/2009/11/28/multi-gateway-routing-with-iptables-and-iproute2/
  • http://backreference.org/2012/10/07/policy-routing-multihoming-and-all-that-jazz/
  • http://www.spinics.net/lists/lartc/msg22937.html
  • http://article.gmane.org/gmane.linux.network/238256

Leave a Reply